00001
00002
00003
#ifdef HAVE_CONFIG_H
00004
#include <config.h>
00005
#endif
00006
00007
#include <sys/types.h>
00008
00009
#ifdef HAVE_SYS_STAT_H
00010
#include <sys/stat.h>
00011
#endif
00012
00013
#include <assert.h>
00014
#include <fcntl.h>
00015
#include <stdlib.h>
00016
#include <unistd.h>
00017
#include <time.h>
00018
00019
#include <qdir.h>
00020
00021
#include <klocale.h>
00022
#include <kmessagebox.h>
00023
#include <kconfig.h>
00024
#include <kdebug.h>
00025
#include <kapplication.h>
00026
00027
#include "kmmainwin.h"
00028
#include "kmfiltermgr.h"
00029
#include "kmfoldermgr.h"
00030
#include "undostack.h"
00031
#include "kmmsgdict.h"
00032
#include "folderstorage.h"
00033
00034
00035 KMFolderMgr::KMFolderMgr(
const QString& aBasePath, KMFolderDirType dirType):
00036
QObject(), mDir(this,
QString::null, dirType)
00037 {
00038
if ( dirType == KMStandardDir )
00039 mDir.setBaseURL( I18N_NOOP(
"Local") );
00040 mQuiet = 0;
00041 mChanged = FALSE;
00042 setBasePath(aBasePath);
00043 mRemoveOrig = 0;
00044 }
00045
00046
00047
00048 KMFolderMgr::~KMFolderMgr()
00049 {
00050
if (kmkernel->undoStack())
00051 kmkernel->undoStack()->clear();
00052 mBasePath = QString::null;
00053 }
00054
00055
00056
00057
void KMFolderMgr::expireAll() {
00058 KConfig *config = KMKernel::config();
00059 KConfigGroupSaver saver(config,
"General");
00060
int ret = KMessageBox::Continue;
00061
00062
if (config->readBoolEntry(
"warn-before-expire",
true)) {
00063 ret = KMessageBox::warningContinueCancel(KMainWindow::memberList->first(),
00064 i18n(
"Are you sure you want to expire old messages?"),
00065 i18n(
"Expire Old Messages?"), i18n(
"Expire"));
00066 }
00067
00068
if (ret == KMessageBox::Continue) {
00069 expireAllFolders(
true );
00070 }
00071
00072 }
00073
00074
#define DO_FOR_ALL(function, folder_code) \
00075
KMFolderNode* node; \
00076
QPtrListIterator<KMFolderNode> it(*dir); \
00077
for ( ; (node = it.current()); ) { \
00078
++it; \
00079
if (node->isDir()) continue; \
00080
KMFolder *folder = static_cast<KMFolder*>(node); \
00081
folder_code \
00082
KMFolderDir *child = folder->child(); \
00083
if (child) \
00084
function \
00085
}
00086
00087
int KMFolderMgr::folderCount(
KMFolderDir *dir)
00088 {
00089
int count = 0;
00090
if (dir == 0)
00091 dir = &mDir;
00092 DO_FOR_ALL(
00093 {
00094 count += folderCount( child );
00095 },
00096 {
00097 count++;
00098 }
00099 )
00100
00101 return count;
00102 }
00103
00104
00105
00106
00107
void KMFolderMgr::compactAllFolders(
bool immediate,
KMFolderDir* dir)
00108 {
00109
if (dir == 0)
00110 dir = &mDir;
00111 DO_FOR_ALL(
00112 {
00113 compactAllFolders( immediate, child );
00114 },
00115 {
00116
if ( folder->needsCompacting() )
00117 folder->compact( immediate ? KMFolder::CompactNow : KMFolder::CompactLater );
00118 }
00119 )
00120 }
00121
00122
00123
00124
void KMFolderMgr::setBasePath(
const QString& aBasePath)
00125 {
00126 assert(!aBasePath.isNull());
00127
00128
if (aBasePath[0] ==
'~')
00129 {
00130 mBasePath = QDir::homeDirPath();
00131 mBasePath.append(
"/");
00132 mBasePath.append(aBasePath.mid(1));
00133 }
00134
else
00135 mBasePath = aBasePath;
00136
00137
QFileInfo info( mBasePath );
00138
00139
00140
00141
if ( info.exists() ) {
00142
if ( !info.isDir() ) {
00143 KMessageBox::sorry(0, i18n(
"'%1' does not appear to be a folder.\n"
00144
"Please move the file out of the way.")
00145 .arg( mBasePath ) );
00146 ::exit(-1);
00147 }
00148
if ( !info.isReadable() || !info.isWritable() ) {
00149 KMessageBox::sorry(0, i18n(
"The permissions of the folder '%1' are "
00150
"incorrect;\n"
00151
"please make sure that you can view and modify "
00152
"the content of this folder.")
00153 .arg( mBasePath ) );
00154 ::exit(-1);
00155 }
00156 }
else {
00157
00158
if ( ::mkdir( QFile::encodeName( mBasePath ) , S_IRWXU ) == -1 ) {
00159 KMessageBox::sorry(0, i18n(
"KMail could not create folder '%1';\n"
00160
"please make sure that you can view and "
00161
"modify the content of the folder '%2'.")
00162 .arg( mBasePath ).arg( QDir::homeDirPath() ) );
00163 ::exit(-1);
00164 }
00165 }
00166 mDir.setPath(mBasePath);
00167 mDir.reload();
00168 contentsChanged();
00169 }
00170
00171
00172
00173
KMFolder* KMFolderMgr::createFolder(
const QString& fName,
bool sysFldr,
00174 KMFolderType aFolderType,
00175
KMFolderDir *aFolderDir)
00176 {
00177
KMFolder* fld;
00178
KMFolderDir *fldDir = aFolderDir;
00179
00180
if (!aFolderDir)
00181 fldDir = &mDir;
00182 fld = fldDir->
createFolder(fName, sysFldr, aFolderType);
00183
if (fld) {
00184 contentsChanged();
00185 emit folderAdded(fld);
00186
if (kmkernel->filterMgr())
00187 kmkernel->filterMgr()->folderCreated(fld);
00188 }
00189
00190
return fld;
00191 }
00192
00193
00194
00195
KMFolder* KMFolderMgr::find(
const QString& folderName,
bool foldersOnly)
00196 {
00197 KMFolderNode* node;
00198
00199
for (node=mDir.first(); node; node=mDir.next())
00200 {
00201
if (node->isDir() && foldersOnly)
continue;
00202
if (node->name()==folderName)
return (
KMFolder*)node;
00203 }
00204
return 0;
00205 }
00206
00207
00208
KMFolder* KMFolderMgr::findById(
const uint
id)
00209 {
00210
return findIdString( QString::null,
id );
00211 }
00212
00213
00214
KMFolder* KMFolderMgr::findIdString(
const QString& folderId,
00215
const uint
id,
00216
KMFolderDir *dir )
00217 {
00218
if (!dir)
00219 dir = &mDir;
00220
00221 DO_FOR_ALL(
00222 {
00223
KMFolder *folder = findIdString( folderId,
id, child );
00224
if ( folder )
00225
return folder;
00226 },
00227 {
00228
if ( ( !folderId.isEmpty() && folder->idString() == folderId ) ||
00229 (
id != 0 && folder->id() ==
id ) )
00230
return folder;
00231 }
00232 )
00233
00234
return 0;
00235 }
00236
00237
void KMFolderMgr::getFolderURLS(
QStringList& flist,
const QString& prefix,
00238
KMFolderDir *adir )
00239 {
00240
KMFolderDir* dir = adir ? adir : &mDir;
00241
00242 DO_FOR_ALL(
00243 {
00244 getFolderURLS( flist, prefix +
"/" + folder->name(), child );
00245 },
00246 {
00247 flist << prefix +
"/" + folder->name();
00248 }
00249 )
00250 }
00251
00252
KMFolder* KMFolderMgr::getFolderByURL(
const QString& vpath,
00253
const QString& prefix,
00254
KMFolderDir *adir )
00255 {
00256
KMFolderDir* dir = adir ? adir : &mDir;
00257 DO_FOR_ALL(
00258 {
00259
QString a = prefix +
"/" + folder->name();
00260
KMFolder * mfolder = getFolderByURL( vpath, a,child );
00261
if ( mfolder )
00262
return mfolder;
00263 },
00264 {
00265
QString comp = prefix +
"/" + folder->name();
00266
if ( comp == vpath )
00267
return folder;
00268 }
00269 )
00270
return 0;
00271 }
00272
00273
00274
KMFolder* KMFolderMgr::findOrCreate(
const QString& aFolderName,
bool sysFldr,
00275
const uint
id)
00276 {
00277
KMFolder* folder = 0;
00278
if (
id == 0 )
00279 folder = find(aFolderName);
00280
else
00281 folder = findById(
id);
00282
00283
if (!folder)
00284 {
00285
static bool know_type =
false;
00286
static KMFolderType type = KMFolderTypeMaildir;
00287
if (know_type ==
false)
00288 {
00289 know_type =
true;
00290 KConfig *config = KMKernel::config();
00291 KConfigGroupSaver saver(config,
"General");
00292
if (config->hasKey(
"default-mailbox-format"))
00293 {
00294
if (config->readNumEntry(
"default-mailbox-format", 1) == 0)
00295 type = KMFolderTypeMbox;
00296
00297 }
00298 }
00299
00300 folder =
createFolder(aFolderName, sysFldr, type);
00301
if (!folder) {
00302 KMessageBox::error(0,(i18n(
"Cannot create file `%1' in %2.\nKMail cannot start without it.").arg(aFolderName).arg(mBasePath)));
00303 exit(-1);
00304 }
00305
if (
id > 0 )
00306 folder->setId(
id );
00307 }
00308
return folder;
00309 }
00310
00311
00312
00313
void KMFolderMgr::remove(
KMFolder* aFolder)
00314 {
00315
if (!aFolder)
return;
00316
00317
if (!mRemoveOrig) mRemoveOrig = aFolder;
00318
if (aFolder->child())
00319 {
00320
00321 KMFolderNode* node;
00322
QPtrListIterator<KMFolderNode> it(*aFolder->child());
00323
for ( ; (node = it.current()); )
00324 {
00325 ++it;
00326
if (node->isDir())
continue;
00327
KMFolder *folder = static_cast<KMFolder*>(node);
00328 remove(folder);
00329 }
00330 }
00331 emit folderRemoved(aFolder);
00332 removeFolder(aFolder);
00333 }
00334
00335
void KMFolderMgr::removeFolder(
KMFolder* aFolder)
00336 {
00337 connect(aFolder, SIGNAL(removed(
KMFolder*,
bool)),
00338
this, SLOT(removeFolderAux(
KMFolder*,
bool)));
00339 aFolder->
remove();
00340 }
00341
00342
void KMFolderMgr::removeFolderAux(
KMFolder* aFolder,
bool success)
00343 {
00344
if (!success) {
00345 mRemoveOrig = 0;
00346
return;
00347 }
00348
00349
KMFolderDir* fdir = aFolder->parent();
00350 KMFolderNode* fN;
00351
for (fN = fdir->first(); fN != 0; fN = fdir->next()) {
00352
if (fN->isDir() && (fN->name() ==
"." + aFolder->
fileName() +
".directory")) {
00353 removeDirAux(static_cast<KMFolderDir*>(fN));
00354
break;
00355 }
00356 }
00357 aFolder->parent()->
remove(aFolder);
00358
00359
QString parentName = fdir->name();
00360 parentName = parentName.mid( 1, parentName.length()-11 );
00361 KMFolderNode* parent = fdir->
hasNamedFolder( parentName );
00362
if ( !parent && fdir->parent() )
00363 parent = fdir->parent()->
hasNamedFolder( parentName );
00364
00365
if ( parent )
00366 static_cast<KMFolder*>(parent)->storage()->updateChildrenState();
00367
else
00368 kdWarning(5006) <<
"Can not find parent folder" << endl;
00369
00370
if (aFolder == mRemoveOrig) {
00371
00372 contentsChanged();
00373 mRemoveOrig = 0;
00374 }
00375 }
00376
00377
void KMFolderMgr::removeDirAux(
KMFolderDir* aFolderDir)
00378 {
00379
QDir dir;
00380
QString folderDirLocation = aFolderDir->
path();
00381 aFolderDir->clear();
00382 aFolderDir->parent()->remove(aFolderDir);
00383 dir.rmdir(folderDirLocation);
00384 }
00385
00386
00387 KMFolderRootDir& KMFolderMgr::dir(
void)
00388 {
00389
return mDir;
00390 }
00391
00392
00393
00394
void KMFolderMgr::contentsChanged(
void)
00395 {
00396
if (mQuiet) mChanged = TRUE;
00397
else emit changed();
00398 }
00399
00400
00401
00402
void KMFolderMgr::reload(
void)
00403 {
00404 }
00405
00406
00407
void KMFolderMgr::createFolderList(
QStringList *str,
00408
QValueList<
QGuardedPtr<KMFolder> > *folders)
00409 {
00410 createFolderList( str, folders, 0,
"" );
00411 }
00412
00413
00414
void KMFolderMgr::createI18nFolderList(
QStringList *str,
00415
QValueList<
QGuardedPtr<KMFolder> > *folders)
00416 {
00417 createFolderList( str, folders, 0, QString::null,
true );
00418 }
00419
00420
00421
void KMFolderMgr::createFolderList(
QStringList *str,
00422
QValueList<
QGuardedPtr<KMFolder> > *folders,
00423
KMFolderDir *adir,
00424
const QString& prefix,
00425
bool i18nized)
00426 {
00427
KMFolderDir* dir = adir ? adir : &mDir;
00428
00429 DO_FOR_ALL(
00430 {
00431 createFolderList(str, folders, child,
" " + prefix, i18nized );
00432 },
00433 {
00434
if (i18nized)
00435 str->append(prefix + folder->
label());
00436
else
00437 str->append(prefix + folder->name());
00438 folders->append( folder );
00439 }
00440 )
00441 }
00442
00443
00444
void KMFolderMgr::syncAllFolders(
KMFolderDir *adir )
00445 {
00446
KMFolderDir* dir = adir ? adir : &mDir;
00447 DO_FOR_ALL(
00448 {
00449 syncAllFolders(child);
00450 },
00451 {
00452
if (folder->
isOpened())
00453 folder->
sync();
00454 }
00455 )
00456 }
00457
00458
00459
00466
void KMFolderMgr::expireAllFolders(
bool immediate,
KMFolderDir *adir) {
00467
KMFolderDir *dir = adir ? adir : &mDir;
00468
00469 DO_FOR_ALL(
00470 {
00471 expireAllFolders(immediate, child);
00472 },
00473 {
00474
if (folder->
isAutoExpire()) {
00475 folder->
expireOldMessages( immediate );
00476 }
00477 }
00478 )
00479 }
00480
00481
00482
void KMFolderMgr::invalidateFolder(KMMsgDict *dict,
KMFolder *folder)
00483 {
00484 unlink(QFile::encodeName(folder->
indexLocation()) +
".sorted");
00485 unlink(QFile::encodeName(folder->
indexLocation()) +
".ids");
00486
if (dict) {
00487 folder->
fillMsgDict(dict);
00488 dict->writeFolderIds(folder);
00489 }
00490 emit folderInvalidated(folder);
00491 }
00492
00493
00494
void KMFolderMgr::readMsgDict(KMMsgDict *dict,
KMFolderDir *dir,
int pass)
00495 {
00496
bool atTop =
false;
00497
if (!dir) {
00498 dir = &mDir;
00499 atTop =
true;
00500 }
00501
00502 DO_FOR_ALL(
00503 {
00504 readMsgDict(dict, child, pass);
00505 },
00506 {
00507
if (pass == 1) {
00508 dict->readFolderIds(folder);
00509 }
else if (pass == 2) {
00510
if (!dict->hasFolderIds(folder)) {
00511 invalidateFolder(dict, folder);
00512 }
00513 }
00514 }
00515 )
00516
00517
if (pass == 1 && atTop)
00518 readMsgDict(dict, dir, pass + 1);
00519 }
00520
00521
00522
void KMFolderMgr::writeMsgDict(KMMsgDict *dict,
KMFolderDir *dir)
00523 {
00524
if (!dir)
00525 dir = &mDir;
00526
00527 DO_FOR_ALL(
00528 {
00529 writeMsgDict(dict, child);
00530 },
00531 {
00532 folder->
writeMsgDict(dict);
00533 }
00534 )
00535 }
00536
00537
00538
void KMFolderMgr::quiet(
bool beQuiet)
00539 {
00540
if (beQuiet)
00541 mQuiet++;
00542
else {
00543 mQuiet--;
00544
if (mQuiet <= 0)
00545 {
00546 mQuiet = 0;
00547
if (mChanged) emit changed();
00548 mChanged = FALSE;
00549 }
00550 }
00551 }
00552
00553
00554
void KMFolderMgr::tryReleasingFolder(
KMFolder* f,
KMFolderDir* adir)
00555 {
00556
KMFolderDir* dir = adir ? adir : &mDir;
00557 DO_FOR_ALL(
00558 {
00559 tryReleasingFolder(f, child);
00560 },
00561 {
00562
if (folder->
isOpened())
00563 folder->
storage()->
tryReleasingFolder(f);
00564 }
00565 )
00566 }
00567
00568
00569 uint KMFolderMgr::createId()
00570 {
00571
int newId;
00572
do
00573 {
00574 newId = kapp->random();
00575 }
while ( findById( newId ) != 0 );
00576
00577
return newId;
00578 }
00579
00580
#include "kmfoldermgr.moc"