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> 39 #include <tdeprocess.h> 40 #include <tdeconfig.h> 52 #include <sys/types.h> 55 #include "broadcaststatus.h" 56 using KPIM::BroadcastStatus;
67 #define MSG_SEPERATOR_START "From " 68 #define MSG_SEPERATOR_START_LEN (sizeof(MSG_SEPERATOR_START) - 1) 69 #define MSG_SEPERATOR_REGEX "^From .*[0-9][0-9]:[0-9][0-9]" 73 KMFolderMbox::KMFolderMbox(
KMFolder* folder,
const char* name)
79 mLockType = lock_none;
84 KMFolderMbox::~KMFolderMbox()
87 close(
"~kmfoldermbox",
true);
88 if (kmkernel->undoStack())
89 kmkernel->undoStack()->folderDestroyed( folder() );
93 int KMFolderMbox::open(
const char *owner)
99 kmkernel->jobScheduler()->notifyOpeningFolder( folder() );
101 if (mOpenCount > 1)
return 0;
103 assert(!folder()->name().isEmpty());
106 mStream = fopen(TQFile::encodeName(
location()),
"r+");
109 KNotifyClient::event( 0,
"warning",
110 i18n(
"Cannot open file \"%1\":\n%2").arg(
location()).arg(strerror(errno)));
111 kdDebug(5006) <<
"Cannot open folder `" <<
location() <<
"': " << strerror(errno) << endl;
118 if (!folder()->path().isEmpty())
122 if (KMFolderIndex::IndexOk != index_status)
126 if (KMFolderIndex::IndexTooOld == index_status) {
127 TQString msg = i18n(
"<qt><p>The index of folder '%2' seems " 128 "to be out of date. To prevent message " 129 "corruption the index will be " 130 "regenerated. As a result deleted " 131 "messages might reappear and status " 132 "flags might be lost.</p>" 133 "<p>Please read the corresponding entry " 134 "in the <a href=\"%1\">FAQ section of the manual " 136 "information about how to prevent this " 137 "problem from happening again.</p></qt>")
138 .arg(
"help:/kmail/faq.html#faq-index-regeneration")
144 if (kmkernel->startingUp())
146 TDEConfigGroup configGroup( KMKernel::config(),
"Notification Messages" );
148 configGroup.readBoolEntry(
"showIndexRegenerationMessage",
true );
150 KMessageBox::queuedMessageBox( 0, KMessageBox::Information,
151 msg, i18n(
"Index Out of Date"),
152 KMessageBox::AllowLink );
157 KMessageBox::information( 0, msg, i18n(
"Index Out of Date"),
158 "showIndexRegenerationMessage",
159 KMessageBox::AllowLink );
164 str = i18n(
"Folder `%1' changed. Recreating index.")
171 updateIndexStreamPtr();
189 fcntl(fileno(mStream), F_SETFD, FD_CLOEXEC);
197 int KMFolderMbox::canAccess()
199 assert(!folder()->name().isEmpty());
201 if (access(TQFile::encodeName(
location()), R_OK | W_OK) != 0) {
202 kdDebug(5006) <<
"KMFolderMbox::access call to access function failed" << endl;
209 int KMFolderMbox::create()
214 assert(!folder()->name().isEmpty());
215 assert(mOpenCount == 0);
217 kdDebug(5006) <<
"Creating folder " << name() << endl;
218 if (access(TQFile::encodeName(
location()), F_OK) == 0) {
219 kdDebug(5006) <<
"KMFolderMbox::create call to access function failed." << endl;
220 kdDebug(5006) <<
"File:: " << endl;
221 kdDebug(5006) <<
"Error " << endl;
225 old_umask = umask(077);
226 mStream = fopen(TQFile::encodeName(
location()),
"w+");
229 if (!mStream)
return errno;
231 fcntl(fileno(mStream), F_SETFD, FD_CLOEXEC);
233 if (!folder()->path().isEmpty())
235 old_umask = umask(077);
237 updateIndexStreamPtr(
true);
258 void KMFolderMbox::reallyDoClose(
const char* owner)
264 kdDebug(5006) <<
"Critical error: " <<
location() <<
265 " has been modified by an external application while KMail was running." << endl;
274 if (mStream) unlock();
277 if (mStream) fclose(mStream);
280 updateIndexStreamPtr(
true);
293 void KMFolderMbox::sync()
296 if (!mStream || fsync(fileno(mStream)) ||
298 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.")));
303 int KMFolderMbox::lock()
313 assert(mStream != 0);
320 rc = fcntl(fileno(mStream), F_SETLKW, &fl);
324 kdDebug(5006) <<
"Cannot lock folder `" <<
location() <<
"': " 325 << strerror(errno) <<
" (" << errno <<
")" << endl;
336 kdDebug(5006) <<
"Cannot lock index of folder `" <<
location() <<
"': " 337 << strerror(errno) <<
" (" << errno <<
")" << endl;
347 case procmail_lockfile:
348 cmd_str =
"lockfile -l20 -r5 ";
349 if (!mProcmailLockFileName.isEmpty())
350 cmd_str += TQFile::encodeName(TDEProcess::quote(mProcmailLockFileName));
352 cmd_str += TQFile::encodeName(TDEProcess::quote(
location() +
".lock"));
354 rc = system( cmd_str.data() );
357 kdDebug(5006) <<
"Cannot lock folder `" <<
location() <<
"': " 358 << strerror(rc) <<
" (" << rc <<
")" << endl;
364 cmd_str =
"lockfile -l20 -r5 " + TQFile::encodeName(TDEProcess::quote(
indexLocation() +
".lock"));
365 rc = system( cmd_str.data() );
368 kdDebug(5006) <<
"Cannot lock index of folder `" <<
location() <<
"': " 369 << strerror(rc) <<
" (" << rc <<
")" << endl;
377 cmd_str =
"mutt_dotlock " + TQFile::encodeName(TDEProcess::quote(
location()));
378 rc = system( cmd_str.data() );
381 kdDebug(5006) <<
"Cannot lock folder `" <<
location() <<
"': " 382 << strerror(rc) <<
" (" << rc <<
")" << endl;
388 cmd_str =
"mutt_dotlock " + TQFile::encodeName(TDEProcess::quote(
indexLocation()));
389 rc = system( cmd_str.data() );
392 kdDebug(5006) <<
"Cannot lock index of folder `" <<
location() <<
"': " 393 << strerror(rc) <<
" (" << rc <<
")" << endl;
400 case mutt_dotlock_privileged:
401 cmd_str =
"mutt_dotlock -p " + TQFile::encodeName(TDEProcess::quote(
location()));
402 rc = system( cmd_str.data() );
405 kdDebug(5006) <<
"Cannot lock folder `" <<
location() <<
"': " 406 << strerror(rc) <<
" (" << rc <<
")" << endl;
412 cmd_str =
"mutt_dotlock -p " + TQFile::encodeName(TDEProcess::quote(
indexLocation()));
413 rc = system( cmd_str.data() );
416 kdDebug(5006) <<
"Cannot lock index of folder `" <<
location() <<
"': " 417 << strerror(rc) <<
" (" << rc <<
")" << endl;
436 KMFolderMbox::doCreateJob(
KMMessage *msg, FolderJob::JobType jt,
437 KMFolder *folder, TQString,
const AttachmentStrategy* )
const 439 MboxJob *job =
new MboxJob( msg, jt, folder );
440 job->setParent(
this );
446 KMFolderMbox::doCreateJob( TQPtrList<KMMessage>& msgList,
const TQString& sets,
447 FolderJob::JobType jt,
KMFolder *folder )
const 449 MboxJob *job =
new MboxJob( msgList, sets, jt, folder );
450 job->setParent(
this );
455 int KMFolderMbox::unlock()
465 assert(mStream != 0);
472 fcntl(fileno(mStream), F_SETLK, &fl);
476 case procmail_lockfile:
478 if (!mProcmailLockFileName.isEmpty())
479 cmd_str += TQFile::encodeName(TDEProcess::quote(mProcmailLockFileName));
481 cmd_str += TQFile::encodeName(TDEProcess::quote(
location() +
".lock"));
483 rc = system( cmd_str.data() );
486 cmd_str =
"rm -f " + TQFile::encodeName(TDEProcess::quote(
indexLocation() +
".lock"));
487 rc = system( cmd_str.data() );
492 cmd_str =
"mutt_dotlock -u " + TQFile::encodeName(TDEProcess::quote(
location()));
493 rc = system( cmd_str.data() );
496 cmd_str =
"mutt_dotlock -u " + TQFile::encodeName(TDEProcess::quote(
indexLocation()));
497 rc = system( cmd_str.data() );
501 case mutt_dotlock_privileged:
502 cmd_str =
"mutt_dotlock -p -u " + TQFile::encodeName(TDEProcess::quote(
location()));
503 rc = system( cmd_str.data() );
506 cmd_str =
"mutt_dotlock -p -u " + TQFile::encodeName(TDEProcess::quote(
indexLocation()));
507 rc = system( cmd_str.data() );
525 return KMFolderIndex::IndexCorrupt;
530 if (!contInfo.exists())
return KMFolderIndex::IndexOk;
531 if (!indInfo.exists())
return KMFolderIndex::IndexMissing;
536 return ( contInfo.lastModified() > indInfo.lastModified().addSecs(5) )
537 ? KMFolderIndex::IndexTooOld
538 : KMFolderIndex::IndexOk;
543 int KMFolderMbox::createIndexFromContents()
546 char status[8], xstatus[8];
547 TQCString subjStr, dateStr, fromStr, toStr, xmarkStr, *lastStr=0;
548 TQCString replyToIdStr, replyToAuxIdStr, referencesStr, msgIdStr;
549 TQCString sizeServerStr, uidStr;
550 TQCString contentTypeStr, charset;
552 bool inHeader =
true;
555 TQRegExp regexp(MSG_SEPERATOR_REGEX);
556 int i, num, numStatus;
559 assert(mStream != 0);
576 replyToAuxIdStr =
"";
580 size_t sizeServer = 0;
586 off_t pos = ftell(mStream);
587 if (!fgets(line, MAX_LINE, mStream)) atEof =
true;
590 (memcmp(line, MSG_SEPERATOR_START, MSG_SEPERATOR_START_LEN)==0 &&
591 regexp.search(line) >= 0))
594 pos = ftell(mStream);
600 msgStr = i18n(
"Creating index file: one message done",
"Creating index file: %n messages done", num);
607 msgIdStr = msgIdStr.stripWhiteSpace();
608 if( !msgIdStr.isEmpty() ) {
610 rightAngle = msgIdStr.find(
'>' );
611 if( rightAngle != -1 )
612 msgIdStr.truncate( rightAngle + 1 );
615 replyToIdStr = replyToIdStr.stripWhiteSpace();
616 if( !replyToIdStr.isEmpty() ) {
618 rightAngle = replyToIdStr.find(
'>' );
619 if( rightAngle != -1 )
620 replyToIdStr.truncate( rightAngle + 1 );
623 referencesStr = referencesStr.stripWhiteSpace();
624 if( !referencesStr.isEmpty() ) {
625 int leftAngle, rightAngle;
626 leftAngle = referencesStr.findRev(
'<' );
627 if( ( leftAngle != -1 )
628 && ( replyToIdStr.isEmpty() || ( replyToIdStr[0] !=
'<' ) ) ) {
630 replyToIdStr = referencesStr.mid( leftAngle );
634 leftAngle = referencesStr.findRev(
'<', leftAngle - 1 );
635 if( leftAngle != -1 )
636 referencesStr = referencesStr.mid( leftAngle );
637 rightAngle = referencesStr.findRev(
'>' );
638 if( rightAngle != -1 )
639 referencesStr.truncate( rightAngle + 1 );
645 replyToAuxIdStr = referencesStr;
646 rightAngle = referencesStr.find(
'>' );
647 if( rightAngle != -1 )
648 replyToAuxIdStr.truncate( rightAngle + 1 );
651 contentTypeStr = contentTypeStr.stripWhiteSpace();
653 if ( !contentTypeStr.isEmpty() )
655 int cidx = contentTypeStr.find(
"charset=" );
657 charset = contentTypeStr.mid( cidx + 8 );
658 if ( !charset.isEmpty() && ( charset[0] ==
'"' ) ) {
659 charset = charset.mid( 1 );
662 while ( (
unsigned int) cidx < charset.length() ) {
663 if ( charset[cidx] ==
'"' || ( !isalnum(charset[cidx]) &&
664 charset[cidx] !=
'-' && charset[cidx] !=
'_' ) )
668 charset.truncate( cidx );
674 mi =
new KMMsgInfo(folder());
675 mi->init( subjStr.stripWhiteSpace(),
676 fromStr.stripWhiteSpace(),
677 toStr.stripWhiteSpace(),
679 xmarkStr.stripWhiteSpace(),
680 replyToIdStr, replyToAuxIdStr, msgIdStr,
681 KMMsgEncryptionStateUnknown, KMMsgSignatureStateUnknown,
682 KMMsgMDNStateUnknown, charset, offs, size, sizeServer, uid );
683 mi->setStatus(status, xstatus);
684 mi->setDate( dateStr.stripWhiteSpace().data() );
693 replyToAuxIdStr =
"";
702 else num--,numStatus++;
705 offs = ftell(mStream);
712 if (inHeader && (line[0]==
'\t' || line[0]==
' '))
715 while (line [i]==
'\t' || line [i]==
' ') i++;
716 if (line [i] <
' ' && line [i]>0) inHeader =
false;
717 else if (lastStr) *lastStr += line + i;
721 if (inHeader && (line [0]==
'\n' || line [0]==
'\r'))
723 if (!inHeader)
continue;
728 if ((needStatus & 1) && strncasecmp(line,
"Status:", 7) == 0)
730 for(i=0; i<4 && line[i+8] >
' '; i++)
731 status[i] = line[i+8];
735 else if ((needStatus & 2) && strncasecmp(line,
"X-Status:", 9)==0)
737 for(i=0; i<4 && line[i+10] >
' '; i++)
738 xstatus[i] = line[i+10];
742 else if (strncasecmp(line,
"X-KMail-Mark:",13)==0)
743 xmarkStr = TQCString(line+13);
744 else if (strncasecmp(line,
"In-Reply-To:",12)==0) {
745 replyToIdStr = TQCString(line+12);
746 lastStr = &replyToIdStr;
748 else if (strncasecmp(line,
"References:",11)==0) {
749 referencesStr = TQCString(line+11);
750 lastStr = &referencesStr;
752 else if (strncasecmp(line,
"Message-Id:",11)==0) {
753 msgIdStr = TQCString(line+11);
756 else if (strncasecmp(line,
"Date:",5)==0)
758 dateStr = TQCString(line+5);
761 else if (strncasecmp(line,
"From:", 5)==0)
763 fromStr = TQCString(line+5);
766 else if (strncasecmp(line,
"To:", 3)==0)
768 toStr = TQCString(line+3);
771 else if (strncasecmp(line,
"Subject:",8)==0)
773 subjStr = TQCString(line+8);
776 else if (strncasecmp(line,
"X-Length:",9)==0)
778 sizeServerStr = TQCString(line+9);
779 sizeServer = sizeServerStr.toULong();
780 lastStr = &sizeServerStr;
782 else if (strncasecmp(line,
"X-UID:",6)==0)
784 uidStr = TQCString(line+6);
785 uid = uidStr.toULong();
788 else if (strncasecmp(line,
"Content-Type:", 13) == 0)
790 contentTypeStr = TQCString(line+13);
791 lastStr = &contentTypeStr;
797 emit
statusMsg(i18n(
"Writing index file"));
804 if (kmkernel->outboxFolder() == folder() &&
count() > 0)
805 KMessageBox::queuedMessageBox(0, KMessageBox::Information,
806 i18n(
"Your outbox contains messages which were " 807 "most-likely not created by KMail;\nplease remove them from there if you " 808 "do not want KMail to send them."));
816 KMMessage* KMFolderMbox::readMsg(
int idx)
818 KMMsgInfo* mi = (KMMsgInfo*)
mMsgList[idx];
820 assert(mi!=0 && !mi->isMessage());
821 assert(mStream != 0);
831 #define STRDIM(x) (sizeof(x)/sizeof(*x)-1) 833 static size_t unescapeFrom(
char* str,
size_t strLen ) {
836 if ( strLen <= STRDIM(
">From ") )
843 const char * s = str;
845 const char *
const e = str + strLen - STRDIM(
">From ");
848 if ( *s ==
'\n' && *(s+1) ==
'>' ) {
851 while ( s < e && *s == '>
' ) 853 if ( tqstrncmp( s, "From ", STRDIM("From ") ) == 0 ) 856 *d++ = *s++; // yes, s might be e here, but e is not the end :-) 859 while ( s < str + strLen ) 861 if ( d < s ) // only NUL-terminate if it's shorter
868 TQByteArray KMFolderMbox::escapeFrom(
const DwString & str ) {
869 const unsigned int strLen = str.length();
870 if ( strLen <= STRDIM(
"From ") )
873 TQByteArray result(
int( strLen + 5 ) / 6 * 7 + 1 );
875 const char * s = str.data();
876 const char *
const e = s + strLen - STRDIM(
"From ");
877 char * d = result.data();
879 bool onlyAnglesAfterLF =
false;
883 onlyAnglesAfterLF =
true;
888 if ( onlyAnglesAfterLF && tqstrncmp( s+1,
"rom ", STRDIM(
"rom ") ) == 0 )
892 onlyAnglesAfterLF =
false;
897 while ( s < str.data() + strLen )
900 result.truncate( d - result.data() );
907 DwString KMFolderMbox::getDwString(
int idx)
909 KMMsgInfo* mi = (KMMsgInfo*)
mMsgList[idx];
912 assert(mStream != 0);
914 size_t msgSize = mi->msgSize();
915 char* msgText =
new char[ msgSize + 1 ];
917 fseek(mStream, mi->folderOffset(), SEEK_SET);
918 fread(msgText, msgSize, 1, mStream);
919 msgText[msgSize] =
'\0';
921 size_t newMsgSize = unescapeFrom( msgText, msgSize );
926 msgStr.TakeBuffer( msgText, msgSize + 1, 0, newMsgSize );
939 bool editing =
false;
943 rc = openThis.openResult();
946 kdDebug(5006) <<
"KMFolderMbox::addMsg-open: " << rc <<
" of folder: " <<
label() << endl;
951 msgParent = aMsg->parent();
954 if ( msgParent== folder() )
956 if (kmkernel->folderIsDraftOrOutbox( folder() ))
959 kdDebug(5006) <<
"Editing message in outbox or drafts" << endl;
966 idx = msgParent->
find(aMsg);
993 size_t len = msgText.size();
995 assert(mStream != 0);
999 kdDebug(5006) <<
"Message added to folder `" << name() <<
"' contains no data. Ignoring it." << endl;
1005 fseek(mStream, 0, SEEK_END);
1006 off_t revert = ftell(mStream);
1007 if (ftell(mStream) >= 2) {
1009 fseek(mStream, -2, SEEK_END);
1010 fread(endStr, 1, 2, mStream);
1011 if (ftell(mStream) > 0 && endStr[0]!=
'\n') {
1013 if (endStr[1]!=
'\n') {
1015 fwrite(
"\n\n", 1, 2, mStream);
1018 else fwrite(
"\n", 1, 1, mStream);
1021 fseek(mStream,0,SEEK_END);
1022 int error = ferror(mStream);
1027 fwrite( messageSeparator.data(), messageSeparator.length(), 1, mStream );
1028 off_t offs = ftell(mStream);
1029 fwrite(msgText.data(), len, 1, mStream);
1030 if (msgText[(
int)len-1]!=
'\n') fwrite(
"\n\n", 1, 2, mStream);
1032 size_t size = ftell(mStream) - offs;
1034 error = ferror(mStream);
1036 kdDebug(5006) <<
"Error: Could not add message to folder: " << strerror(errno) << endl;
1037 if (ftell(mStream) > revert) {
1038 kdDebug(5006) <<
"Undoing changes" << endl;
1039 truncate( TQFile::encodeName(
location()), revert );
1041 kmkernel->emergencyExit( i18n(
"Could not add message to folder: ") + TQString::fromLocal8Bit(strerror(errno)));
1057 if (idx >= 0) msgParent->
take(idx);
1061 if (aMsg->isUnread() || aMsg->isNew() ||
1062 (folder() == kmkernel->outboxFolder())) {
1071 if ( aMsg->attachmentState() == KMMsgAttachmentUnknown && aMsg->
readyToShow() ) {
1072 aMsg->updateAttachmentState();
1074 if ( aMsg->invitationState() == KMMsgInvitationUnknown && aMsg->
readyToShow() ) {
1075 aMsg->updateInvitationState();
1079 aMsg->setParent(folder());
1080 aMsg->setFolderOffset(offs);
1081 aMsg->setMsgSize(size);
1083 if ( aMsg->getMsgSerNum() <= 0 )
1089 if ((idx > 0) && (growth > 0)) {
1091 if ((ulong)revert ==
mMsgList[idx - 1]->folderOffset() +
mMsgList[idx - 1]->msgSize() )
1105 const uchar *buffer = mb->asIndexString(len);
1108 mb->setIndexLength( len );
1110 kdDebug(5006) <<
"Whoa! " << __FILE__ <<
":" << __LINE__ << endl;
1119 kdWarning(5006) <<
"Error: Could not add message to folder (No space left on device?)" << endl;
1121 kdWarning(5006) <<
"Undoing changes" << endl;
1125 kmkernel->emergencyExit( i18n(
"Could not add message to folder:") + TQString::fromLocal8Bit(strerror(errno)));
1127 kmkernel->emergencyExit( i18n(
"Could not add message to folder (No space left on device?)") );
1142 if (aIndex_ret) *aIndex_ret = idx;
1151 int KMFolderMbox::compact(
unsigned int startIndex,
int nbMessages, FILE* tmpfile, off_t& offs,
bool& done )
1155 unsigned int stopIndex = nbMessages == -1 ?
mMsgList.
count() :
1158 for(
unsigned int idx = startIndex; idx < stopIndex; ++idx) {
1159 KMMsgInfo* mi = (KMMsgInfo*)
mMsgList.at(idx);
1160 size_t msize = mi->msgSize();
1161 if (mtext.size() < msize + 2)
1163 off_t folder_offset = mi->folderOffset();
1166 for(off_t i = folder_offset-25;
true; i -= 20) {
1167 off_t chunk_offset = i <= 0 ? 0 : i;
1168 if(fseek(mStream, chunk_offset, SEEK_SET) == -1) {
1172 if (mtext.size() < 20)
1174 fread(mtext.data(), 20, 1, mStream);
1176 if ( mtext.contains(
"from ",
false ) ) {
1177 if (mtext.size() < (size_t)folder_offset)
1178 mtext.resize(folder_offset);
1179 if(fseek(mStream, chunk_offset, SEEK_SET) == -1 ||
1180 !fread(mtext.data(), folder_offset, 1, mStream) ||
1181 !fwrite(mtext.data(), folder_offset, 1, tmpfile)) {
1185 offs += folder_offset;
1192 for(
int i2 = 0; i2 < 20; i2++) {
1193 if(*(mtext.data()+i2) ==
'\n')
1196 if(last_crlf != -1) {
1197 int size = folder_offset - (i + last_crlf+1);
1198 if ((
int)mtext.size() < size)
1200 if(fseek(mStream, i + last_crlf+1, SEEK_SET) == -1 ||
1201 !fread(mtext.data(), size, 1, mStream) ||
1202 !fwrite(mtext.data(), size, 1, tmpfile)) {
1215 if(fseek(mStream, folder_offset, SEEK_SET) == -1 ||
1216 !fread(mtext.data(), msize, 1, mStream) || !fwrite(mtext.data(), msize, 1, tmpfile)) {
1220 mi->setFolderOffset(offs);
1228 int KMFolderMbox::compact(
bool silent )
1234 int rc = job->executeNow( silent );
1239 TQString
statusMsg = BroadcastStatus::instance()->statusMsg();
1241 BroadcastStatus::instance()->setStatusMsg( statusMsg );
1247 void KMFolderMbox::setLockType( LockType ltype )
1253 void KMFolderMbox::setProcmailLockFileName(
const TQString &fname )
1255 mProcmailLockFileName = fname;
1259 int KMFolderMbox::removeContents()
1262 rc = unlink(TQFile::encodeName(
location()));
1267 int KMFolderMbox::expungeContents()
1270 if (truncate(TQFile::encodeName(
location()), 0))
1277 TQ_INT64 KMFolderMbox::doFolderSize()
const 1280 return (TQ_INT64)(info.size());
1284 #include "kmfoldermbox.moc" A job that runs in the background and compacts mbox folders.
virtual TQString indexLocation() const
Returns full path to index file.
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. ...
const DwString & asDwString() const
Return the entire message contents in the DwString.
KMMessage * take(int idx)
Detach message from this folder.
IndexStatus
This enum indicates the status of the index file.
virtual KMFolderType folderType() const
Returns the type of this folder.
RAII for KMFolder::open() / close().
virtual int updateIndex()
Incrementally update the index if possible else call writeIndex.
KMMsgBase & toMsgBase()
Get KMMsgBase for this object.
FILE * mIndexStream
table of contents file
void setStatusFields()
Set "Status" and "X-Status" fields of the message from the internal message status.
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 location() const
Returns full path to folder file.
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.
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.
void clear(bool autoDelete=true, bool syncDict=false)
Clear messages.
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.
int find(const KMMsgBase *msg) const
Returns the index of the given message or -1 if not found.
void replaceMsgSerNum(unsigned long sernum, KMMsgBase *msg, int idx)
Replaces the serial number for the message msg at index idx with sernum.
virtual bool noContent() const
Returns, if the folder can't contain mails, but only subfolder.
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 ...
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.
TQString label() const
Returns the label of the folder for visualization.
virtual IndexStatus indexStatus()=0
Tests whether the contents of this folder is newer than the index.
bool readyToShow() const
Return if the message is ready to be shown.
virtual int addMsg(TQPtrList< KMMessage > &, TQValueList< int > &index_return)
Adds the given messages to the folder.
TQString headerField(const TQCString &name) const
Returns the value of a header field with the given name.
virtual int count(bool cache=false) const
Number of messages in this folder.
unsigned int count() const
Number of messages in the array.
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.