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.
541 lines
14 KiB
541 lines
14 KiB
#include <dirent.h> |
|
#include <sys/stat.h> |
|
#include <unistd.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
|
|
#include <qdir.h> |
|
#include <qstring.h> |
|
|
|
#include <kdebug.h> |
|
#include <kmessagebox.h> |
|
#include <klocale.h> |
|
#include <kapp.h> |
|
#include <kstddirs.h> |
|
|
|
#include <kmailIface.h> |
|
|
|
#include "kmkernel.h" |
|
#include "kmmainwin.h" |
|
#include "kmcomposewin.h" |
|
#include "kmmessage.h" |
|
#include "kmfoldermgr.h" |
|
#include "kmfolder.h" |
|
#include "kmfiltermgr.h" |
|
#include "kmreaderwin.h" |
|
#include "kmsender.h" |
|
#include "kmundostack.h" |
|
#include "kmidentity.h" |
|
#include "kmacctmgr.h" |
|
#include "kbusyptr.h" |
|
#include "kmaddrbook.h" |
|
#include <kabapi.h> |
|
#include <kwin.h> |
|
|
|
#include <X11/Xlib.h> |
|
|
|
KMKernel *KMKernel::mySelf = 0; |
|
|
|
/********************************************************************/ |
|
/* Constructor and destructor */ |
|
/********************************************************************/ |
|
KMKernel::KMKernel (QObject *parent, const char *name) : |
|
QObject(parent, name), DCOPObject("KMailIface") |
|
{ |
|
//debug ("KMKernel::KMKernel"); |
|
mySelf = this; |
|
} |
|
|
|
KMKernel::~KMKernel () |
|
{ |
|
mySelf = 0; |
|
debug ("KMKernel::~KMKernel"); |
|
} |
|
|
|
|
|
/********************************************************************/ |
|
/* DCOP-callable, and command line actions */ |
|
/********************************************************************/ |
|
void KMKernel::checkMail () //might create a new reader but won´t show!! |
|
{ |
|
debug ("KMKernel::checkMail called"); |
|
KMMainWin *mWin = 0; |
|
|
|
if (kapp->mainWidget() && kapp->mainWidget()->isA("KMMainWin")) |
|
mWin = (KMMainWin *) kapp->mainWidget(); |
|
else |
|
mWin = new KMMainWin; |
|
mWin->slotCheckMail(); |
|
} |
|
|
|
void KMKernel::openReader( KURL /*messageFile*/) |
|
{ |
|
#warning Ugly hack! (sven) |
|
KMMainWin *mWin = 0; |
|
KMainWindow *ktmw = 0; |
|
debug ("KMKernel::openReader called"); |
|
|
|
if (KMainWindow::memberList) |
|
for (ktmw = KMainWindow::memberList->first(); ktmw; |
|
ktmw = KMainWindow::memberList->next()) |
|
if (ktmw->isA("KMMainWin")) |
|
break; |
|
|
|
if (ktmw) |
|
mWin = (KMMainWin *) ktmw; |
|
else |
|
mWin = new KMMainWin; |
|
mWin->show(); |
|
KWin::setActiveWindow(mWin->winId()); |
|
//and "Activate" by kwin? |
|
|
|
//if (!messageFile.isEmpty()) |
|
// mWin->viewMessage(messageFile); |
|
} |
|
|
|
int KMKernel::openComposer (QString to, QString cc, |
|
QString bcc, QString subject, int hidden) |
|
{ |
|
debug ("KMKernel::openComposer called"); |
|
|
|
KMMessage *msg = new KMMessage; |
|
msg->initHeader(); |
|
if (!cc.isEmpty()) msg->setCc(cc); |
|
if (!bcc.isEmpty()) msg->setBcc(bcc); |
|
if (!subject.isEmpty()) msg->setSubject(subject); |
|
if (!to.isEmpty()) msg->setTo(to); |
|
|
|
KMComposeWin *cWin = new KMComposeWin(msg); |
|
if (hidden == 0) |
|
cWin->show(); |
|
//return cWin->composerId() |
|
return 1; |
|
} |
|
|
|
int KMKernel::setBody (int /*composerId*/, QString /*body*/) |
|
{ |
|
debug ("KMKernel::setBody called"); |
|
return 1; |
|
} |
|
|
|
int KMKernel::addAttachment(int /*composerId*/, KURL /*url*/, |
|
QString /*comment*/) |
|
{ |
|
debug ("KMKernel::addAttachment called"); |
|
return 1; |
|
} |
|
|
|
int KMKernel::send(int /*composerId*/, int /*when*/) |
|
{ |
|
debug ("KMKernel::send called"); |
|
return 1; |
|
} |
|
|
|
int KMKernel::ready() |
|
{ |
|
debug ("KMKernel::ready called"); |
|
return 1; |
|
} |
|
|
|
/********************************************************************/ |
|
/* Kernel methods */ |
|
/********************************************************************/ |
|
|
|
void KMKernel::quit() |
|
{ |
|
// Called when all windows are closed. Will take care of compacting, |
|
// sending... should handle session management too!! |
|
|
|
if (msgSender() && msgSender()->sending()) // sender working? |
|
{ |
|
kernel->msgSender()->quitWhenFinished(); // tell him to quit app when finished |
|
return; // don't quit now |
|
} |
|
kapp->quit(); // sender not working, quit |
|
} |
|
/* TODO later: |
|
Asuming that: |
|
- msgsender is nonblocking |
|
(our own, QSocketNotifier based. Pops up errors and sends signal |
|
senderFinished when done) |
|
- compacting is non blocking (insert processEvents there) |
|
|
|
o If we are getting mail, stop it (but don´t lose something!) |
|
o If we are sending mail, go on UNLESS this was called by SM, |
|
in which case stop ASAP that too (can we warn? should we continue |
|
on next start?) |
|
o If we are compacting, or expunging, go on UNLESS this was SM call. |
|
In that case stop compacting ASAP and continue on next start, before |
|
touching any folders. |
|
|
|
KMKernel::quit () |
|
{ |
|
SM call? |
|
if compacting, stop; |
|
if sending, stop; |
|
if receiving, stop; |
|
Windows will take care of themselves (composer should dump |
|
it´s messages, if any but not in deadMail) |
|
declare us ready for the End of the Session |
|
|
|
No, normal quit call |
|
All windows are off. Anything to do, should compact or sender sends? |
|
Yes, maybe put an icon in panel as a sign of life |
|
Folder manager, go compacting (*except* outbox and sent-mail!) |
|
if sender sending, connect us to his finished slot, declare us ready |
|
for quit and wait for senderFinished |
|
if not, Folder manager, go compact sent-mail and outbox |
|
} (= call slotFinished()) |
|
|
|
void KMKernel::slotSenderFinished() |
|
{ |
|
good, Folder manager go compact sent-mail and outbox |
|
clean up stage1 (release folders and config, unregister from dcop) |
|
-- another kmail may start now --- |
|
kapp->quit(); |
|
} |
|
|
|
void KMKernel:: |
|
void KMKernel:: |
|
*/ |
|
|
|
|
|
/********************************************************************/ |
|
/* Init, Exit, and handler methods */ |
|
/********************************************************************/ |
|
void KMKernel::testDir(const char *_name) |
|
{ |
|
DIR *dp; |
|
QString c = getenv("HOME"); |
|
if(c.isEmpty()) |
|
{ |
|
KMessageBox::sorry(0, i18n("$HOME is not set!\n" |
|
"KMail cannot start without it.\n")); |
|
exit(-1); |
|
} |
|
|
|
c += _name; |
|
dp = opendir(c.data()); |
|
if (dp == NULL) ::mkdir(c.data(), S_IRWXU); |
|
else closedir(dp); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Open a composer for each message found in ~/dead.letter |
|
//to control |
|
void KMKernel::recoverDeadLetters(void) |
|
{ |
|
KMComposeWin* win; |
|
KMMessage* msg; |
|
QDir dir = QDir::home(); |
|
QString fname = dir.path(); |
|
int i, rc, num; |
|
|
|
if (!dir.exists("dead.letter")) return; |
|
fname += "/dead.letter"; |
|
KMFolder folder(0, fname); |
|
|
|
folder.setAutoCreateIndex(FALSE); |
|
rc = folder.open(); |
|
if (rc) |
|
{ |
|
perror("cannot open file "+fname); |
|
return; |
|
} |
|
|
|
folder.quiet(TRUE); |
|
folder.open(); |
|
|
|
num = folder.count(); |
|
for (i=0; i<num; i++) |
|
{ |
|
msg = folder.take(0); |
|
if (msg) |
|
{ |
|
win = new KMComposeWin; |
|
win->setMsg(msg, FALSE); |
|
win->show(); |
|
} |
|
} |
|
folder.close(); |
|
unlink(fname); |
|
} |
|
|
|
void KMKernel::initFolders(KConfig* cfg) |
|
{ |
|
QString name; |
|
|
|
name = cfg->readEntry("inboxFolder"); |
|
|
|
// Currently the folder manager cannot manage folders which are not |
|
// in the base folder directory. |
|
//if (name.isEmpty()) name = getenv("MAIL"); |
|
|
|
if (name.isEmpty()) name = "inbox"; |
|
|
|
the_inboxFolder = (KMFolder*)the_folderMgr->findOrCreate(name); |
|
the_inboxFolder->setSystemFolder(TRUE); |
|
// inboxFolder->open(); |
|
|
|
the_outboxFolder = the_folderMgr->findOrCreate(cfg->readEntry("outboxFolder", "outbox")); |
|
the_outboxFolder->setType("Out"); |
|
the_outboxFolder->setWhoField("To"); |
|
the_outboxFolder->setSystemFolder(TRUE); |
|
the_outboxFolder->open(); |
|
|
|
the_sentFolder = the_folderMgr->findOrCreate(cfg->readEntry("sentFolder", "sent-mail")); |
|
the_sentFolder->setType("St"); |
|
the_sentFolder->setWhoField("To"); |
|
the_sentFolder->setSystemFolder(TRUE); |
|
the_sentFolder->open(); |
|
|
|
the_trashFolder = the_folderMgr->findOrCreate(cfg->readEntry("trashFolder", "trash")); |
|
the_trashFolder->setType("Tr"); |
|
the_trashFolder->setSystemFolder(TRUE); |
|
the_trashFolder->open(); |
|
|
|
} |
|
|
|
|
|
void KMKernel::init() |
|
{ |
|
debug ("entering KMKernel::init()"); |
|
QCString acctPath, foldersPath; |
|
KConfig* cfg; |
|
|
|
the_checkingMail = false; |
|
the_shuttingDown = false; |
|
the_server_is_ready = false; |
|
mUseKAB = false; |
|
|
|
the_kbp = new KBusyPtr; |
|
cfg = kapp->config(); |
|
//debug ("1"); |
|
// Stefan: Yes, we really want this message handler. Without it, |
|
// kmail does not show vital warning() dialogs. |
|
//qInstallMsgHandler(&kmailMsgHandler); |
|
|
|
QDir dir; |
|
QString d = locateLocal("data", "kmail/"); |
|
|
|
cfg->setGroup("General"); |
|
the_firstStart = cfg->readBoolEntry("first-start", true); |
|
foldersPath = cfg->readEntry("folders", ""); |
|
acctPath = cfg->readEntry("accounts", foldersPath + "/.kmail-accounts"); |
|
|
|
if (foldersPath.isEmpty()) |
|
{ |
|
foldersPath = QDir::homeDirPath() + QString("/Mail"); |
|
transferMail(); |
|
} |
|
|
|
the_undoStack = new KMUndoStack(20); |
|
the_folderMgr = new KMFolderMgr(foldersPath); |
|
the_acctMgr = new KMAcctMgr(acctPath); |
|
the_filterMgr = new KMFilterMgr; |
|
the_filterActionDict = new KMFilterActionDict; |
|
the_addrBook = new KMAddrBook; |
|
the_KAB_addrBook=0; |
|
|
|
initFolders(cfg); |
|
the_acctMgr->readConfig(); |
|
the_filterMgr->readConfig(); |
|
the_addrBook->readConfig(); |
|
if(the_addrBook->load() == IO_FatalError) |
|
{ |
|
KMessageBox::sorry(0, i18n("The addressbook could not be loaded.")); |
|
} |
|
KMMessage::readConfig(); |
|
the_msgSender = new KMSender; |
|
|
|
|
|
the_server_is_ready = true; |
|
|
|
// filterMgr->dump(); |
|
debug ("exiting KMKernel::init()"); |
|
} |
|
|
|
bool KMKernel::doSessionManagement() |
|
{ |
|
|
|
// Do session management |
|
if (kapp->isRestored()){ |
|
int n = 1; |
|
while (KTMainWindow::canBeRestored(n)){ |
|
//only restore main windows! (Matthias); |
|
if (KTMainWindow::classNameOfToplevel(n) == "KMMainWin") |
|
(new KMMainWin)->restore(n); |
|
n++; |
|
} |
|
return true; // we were restored by SM |
|
} |
|
return false; // no, we were not restored |
|
} |
|
|
|
void KMKernel::cleanup(void) |
|
{ |
|
the_shuttingDown = TRUE; |
|
KConfig* config = kapp->config(); |
|
|
|
if (the_trashFolder) { |
|
the_trashFolder->close(TRUE); |
|
config->setGroup("General"); |
|
if (config->readBoolEntry("empty-trash-on-exit", true)) |
|
the_trashFolder->expunge(); |
|
} |
|
|
|
if (the_folderMgr) { |
|
if (config->readBoolEntry("compact-all-on-exit", true)) |
|
the_folderMgr->compactAll(); // I can compact for ages in peace now! |
|
} |
|
|
|
if (the_inboxFolder) the_inboxFolder->close(TRUE); |
|
if (the_outboxFolder) the_outboxFolder->close(TRUE); |
|
if (the_sentFolder) the_sentFolder->close(TRUE); |
|
|
|
if (the_msgSender) delete the_msgSender; |
|
if (the_addrBook) delete the_addrBook; |
|
if (the_filterMgr) delete the_filterMgr; |
|
if (the_acctMgr) delete the_acctMgr; |
|
if (the_folderMgr) delete the_folderMgr; |
|
if (the_kbp) delete the_kbp; |
|
|
|
//qInstallMsgHandler(oldMsgHandler); |
|
kapp->config()->sync(); |
|
//--- Sven's save attachments to /tmp start --- |
|
//debug ("cleaned"); |
|
QString cmd; |
|
// This is a dir with attachments and it is not critical if they are |
|
// left behind. |
|
if (!KMReaderWin::attachDir().isEmpty()) |
|
{ |
|
cmd.sprintf("rm -rf '%s'", (const char*)KMReaderWin::attachDir()); |
|
system (cmd.data()); // delete your owns only |
|
} |
|
//--- Sven's save attachments to /tmp end --- |
|
} |
|
|
|
//Isn´t this obsolete? (sven) |
|
void KMKernel::transferMail(void) |
|
{ |
|
QDir dir = QDir::home(); |
|
int rc; |
|
|
|
// Stefan: This function is for all the whiners who think that KMail is |
|
// broken because they cannot read mail with pine and do not |
|
// know how to fix this problem with a simple symbolic link =;-) |
|
// Markus: lol ;-) |
|
if (!dir.cd("KMail")) return; |
|
|
|
rc = KMessageBox::questionYesNo(0, |
|
i18n( |
|
"The directory ~/KMail exists. From now on, KMail uses the\n" |
|
"directory ~/Mail for its messages.\n" |
|
"KMail can move the contents of the directory ~/KMail into\n" |
|
"~/Mail, but this will replace existing files with the same\n" |
|
"name in the directory ~/Mail (e.g. inbox).\n\n" |
|
"Shall KMail move the mail folders now ?")); |
|
|
|
if (rc == KMessageBox::No) return; |
|
|
|
dir.cd("/"); // otherwise we lock the directory |
|
testDir("/Mail"); |
|
system("mv -f ~/KMail/* ~/Mail"); |
|
system("mv -f ~/KMail/.??* ~/Mail"); |
|
system("rmdir ~/KMail"); |
|
} |
|
|
|
|
|
void KMKernel::ungrabPtrKb(void) |
|
{ |
|
if(!KTMainWindow::memberList) return; |
|
QWidget* widg = KTMainWindow::memberList->first(); |
|
Display* dpy; |
|
|
|
if (!widg) return; |
|
dpy = widg->x11Display(); |
|
XUngrabKeyboard(dpy, CurrentTime); |
|
XUngrabPointer(dpy, CurrentTime); |
|
} |
|
|
|
|
|
// Message handler |
|
void KMKernel::kmailMsgHandler(QtMsgType aType, const char* aMsg) |
|
{ |
|
QString appName = kapp->caption(); |
|
QString msg = aMsg; |
|
static int recurse=-1; |
|
|
|
recurse++; |
|
|
|
switch (aType) |
|
{ |
|
case QtDebugMsg: |
|
kdDebug() << msg; |
|
break; |
|
|
|
case QtWarningMsg: |
|
fprintf(stderr, "%s: %s\n", (const char*)kapp->name(), msg.data()); |
|
kdDebug() << msg; |
|
break; |
|
|
|
case QtFatalMsg: |
|
ungrabPtrKb(); |
|
fprintf(stderr, appName+" "+i18n("fatal error")+": %s\n", msg.data()); |
|
KMessageBox::error(0, aMsg); |
|
abort(); |
|
} |
|
|
|
recurse--; |
|
} |
|
void KMKernel::dumpDeadLetters() |
|
{ |
|
QWidget *win; |
|
|
|
while (KTMainWindow::memberList->first() != 0) |
|
{ |
|
win = KTMainWindow::memberList->take(); |
|
if (win->inherits("KMComposeWin")) ((KMComposeWin*)win)->deadLetter(); |
|
// delete win; // WABA: Don't delete, we might crash in there! |
|
} |
|
cleanup(); |
|
} |
|
|
|
|
|
|
|
void KMKernel::action(bool mailto, bool check, QString to, QString cc, |
|
QString bcc, QString subj, KURL messageFile) |
|
{ |
|
|
|
if (mailto) |
|
openComposer (to, cc, bcc, subj, 0); |
|
else |
|
openReader(messageFile); |
|
|
|
if (check) |
|
checkMail(); |
|
//Anything else? |
|
} |
|
|
|
KabAPI* KMKernel::KABaddrBook() |
|
{ |
|
if (the_KAB_addrBook) |
|
return the_KAB_addrBook; |
|
|
|
the_KAB_addrBook = new KabAPI; // KabApi is a dialog; |
|
CHECK_PTR(the_KAB_addrBook); |
|
if(KABaddrBook()->init()!=AddressBook::NoError) |
|
{ // this connects to the default address book and opens it: |
|
debug( "Error initializing the connection to your KAB address book." ); |
|
the_KAB_addrBook=0; |
|
} |
|
else { |
|
debug ("KMKernel::init: KabApi initialized."); |
|
} |
|
|
|
return the_KAB_addrBook; |
|
} |
|
|
|
|
|
#include "kmkernel.moc"
|
|
|