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.
 
 
 

519 lines
14 KiB

/**
* kmacctimap.cpp
*
* Copyright (c) 2000-2002 Michael Haeckel <haeckel@kde.org>
*
* This file is based on kmacctexppop.cpp by Don Sanders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "kmacctimap.moc"
#include "kmbroadcaststatus.h"
#include "kmfoldertree.h"
#include "kmfoldermgr.h"
#include "kmfiltermgr.h"
#include <kmfolderimap.h>
#include <kio/passdlg.h>
#include <kio/scheduler.h>
#include <kio/slave.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <qregexp.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <netinet/in.h>
#include <assert.h>
//-----------------------------------------------------------------------------
KMAcctImap::KMAcctImap(KMAcctMgr* aOwner, const QString& aAccountName):
KMAcctImapInherited(aOwner, aAccountName)
{
init();
mSlave = NULL;
mTotal = 0;
mFolder = 0;
connect(KMBroadcastStatus::instance(), SIGNAL(signalAbortRequested()),
this, SLOT(slotAbortRequested()));
connect(&mIdleTimer, SIGNAL(timeout()), SLOT(slotIdleTimeout()));
KIO::Scheduler::connect(
SIGNAL(slaveError(KIO::Slave *, int, const QString &)),
this, SLOT(slotSlaveError(KIO::Slave *, int, const QString &)));
}
//-----------------------------------------------------------------------------
KMAcctImap::~KMAcctImap()
{
killAllJobs();
if (mSlave) KIO::Scheduler::disconnectSlave(mSlave);
emit deleted(this);
}
//-----------------------------------------------------------------------------
QString KMAcctImap::type(void) const
{
return "imap";
}
//-----------------------------------------------------------------------------
void KMAcctImap::init(void)
{
mHost = "";
mPort = 143;
mLogin = "";
mPasswd = "";
mAuth = "*";
mStorePasswd = FALSE;
mAskAgain = FALSE;
mProgressEnabled = FALSE;
mPrefix = "/";
mAutoExpunge = TRUE;
mHiddenFolders = FALSE;
mOnlySubscribedFolders = FALSE;
mUseSSL = FALSE;
mUseTLS = FALSE;
mIdle = TRUE;
}
//-----------------------------------------------------------------------------
void KMAcctImap::pseudoAssign(KMAccount* account)
{
mIdleTimer.stop();
killAllJobs();
if (mSlave) KIO::Scheduler::disconnectSlave(mSlave);
mSlave = NULL;
if (mFolder)
{
mFolder->setContentState(KMFolderImap::imapNoInformation);
mFolder->setSubfolderState(KMFolderImap::imapNoInformation);
}
assert(account->type() == "imap");
KMAcctImap *acct = static_cast<KMAcctImap*>(account);
setName(acct->name());
setCheckInterval(acct->checkInterval());
setCheckExclude(acct->checkExclude());
setFolder(acct->folder());
setHost(acct->host());
setPort(acct->port());
setPrefix(acct->prefix());
setLogin(acct->login());
setTrash(acct->trash());
setAuth(acct->auth());
setAutoExpunge(acct->autoExpunge());
setHiddenFolders(acct->hiddenFolders());
setOnlySubscribedFolders(acct->onlySubscribedFolders());
setStorePasswd(acct->storePasswd());
setPasswd(acct->passwd(), acct->storePasswd());
setUseSSL(acct->useSSL());
setUseTLS(acct->useTLS());
}
//-----------------------------------------------------------------------------
void KMAcctImap::readConfig(KConfig& config)
{
KMAcctImapInherited::readConfig(config);
mLogin = config.readEntry("login", "");
mStorePasswd = config.readNumEntry("store-passwd", FALSE);
if (mStorePasswd)
{
mPasswd = config.readEntry("pass");
if (mPasswd.isEmpty())
{
mPasswd = config.readEntry("passwd");
if (!mPasswd.isEmpty()) mPasswd = importPassword(mPasswd);
}
}
else mPasswd = "";
mHost = config.readEntry("host");
mPort = config.readNumEntry("port");
mAuth = config.readEntry("auth", "*");
mPrefix = config.readEntry("prefix", "/");
mTrash = config.readEntry("trash");
if (mFolder) mFolder->setImapPath(mPrefix);
mAutoExpunge = config.readBoolEntry("auto-expunge", TRUE);
mHiddenFolders = config.readBoolEntry("hidden-folders", FALSE);
mOnlySubscribedFolders = config.readBoolEntry("subscribed-folders", FALSE);
mUseSSL = config.readBoolEntry("use-ssl", FALSE);
mUseTLS = config.readBoolEntry("use-tls", FALSE);
}
//-----------------------------------------------------------------------------
void KMAcctImap::writeConfig(KConfig& config)
{
KMAcctImapInherited::writeConfig(config);
config.writeEntry("login", mLogin);
config.writeEntry("store-passwd", mStorePasswd);
if (mStorePasswd) config.writeEntry("pass", mPasswd);
else config.writeEntry("passwd", "");
config.writeEntry("host", mHost);
config.writeEntry("port", static_cast<int>(mPort));
config.writeEntry("auth", mAuth);
config.writeEntry("prefix", mPrefix);
config.writeEntry("trash", mTrash);
config.writeEntry("auto-expunge", mAutoExpunge);
config.writeEntry("hidden-folders", mHiddenFolders);
config.writeEntry("subscribed-folders", mOnlySubscribedFolders);
config.writeEntry("use-ssl", mUseSSL);
config.writeEntry("use-tls", mUseTLS);
}
//-----------------------------------------------------------------------------
void KMAcctImap::setStorePasswd(bool b)
{
mStorePasswd = b;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setUseSSL(bool b)
{
mUseSSL = b;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setUseTLS(bool b)
{
mUseTLS = b;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setLogin(const QString& aLogin)
{
mLogin = aLogin;
}
//-----------------------------------------------------------------------------
QString KMAcctImap::passwd(void) const
{
return decryptStr(mPasswd);
}
//-----------------------------------------------------------------------------
void KMAcctImap::setPasswd(const QString& aPasswd, bool aStoreInConfig)
{
mPasswd = encryptStr(aPasswd);
mStorePasswd = aStoreInConfig;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setHost(const QString& aHost)
{
mHost = aHost;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setPort(unsigned short int aPort)
{
mPort = aPort;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setPrefix(const QString& aPrefix)
{
mPrefix = aPrefix;
mPrefix.replace(QRegExp("[%*\"]"), "");
if (mPrefix.isEmpty() || mPrefix.at(0) != '/') mPrefix = '/' + mPrefix;
if (mPrefix.at(mPrefix.length() - 1) != '/') mPrefix += '/';
if (mFolder) mFolder->setImapPath(mPrefix);
}
//-----------------------------------------------------------------------------
void KMAcctImap::setTrash(const QString& aTrash)
{
mTrash = aTrash;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setImapFolder(KMFolderImap *aFolder)
{
mFolder = aFolder;
mFolder->setImapPath(mPrefix);
}
//-----------------------------------------------------------------------------
void KMAcctImap::initJobData(jobData &jd)
{
jd.total = 1;
jd.done = 0;
jd.parent = NULL;
jd.quiet = FALSE;
jd.inboxOnly = FALSE;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setAutoExpunge(bool aAutoExpunge)
{
mAutoExpunge = aAutoExpunge;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setHiddenFolders(bool aHiddenFolders)
{
mHiddenFolders = aHiddenFolders;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setOnlySubscribedFolders(bool aOnlySubscribedFolders)
{
mOnlySubscribedFolders = aOnlySubscribedFolders;
}
//-----------------------------------------------------------------------------
void KMAcctImap::setAuth(const QString& aAuth)
{
mAuth = aAuth;
}
//-----------------------------------------------------------------------------
void KMAcctImap::initSlaveConfig()
{
mSlaveConfig.clear();
mSlaveConfig.insert("auth", mAuth);
mSlaveConfig.insert("tls", (mUseTLS) ? "on" : "off");
if (mAutoExpunge) mSlaveConfig.insert("expunge", "auto");
}
//-----------------------------------------------------------------------------
KURL KMAcctImap::getUrl()
{
KURL url;
url.setProtocol(mUseSSL ? QString("imaps") : QString("imap"));
url.setUser(mLogin);
url.setPass(decryptStr(mPasswd));
url.setHost(mHost);
url.setPort(mPort);
return url;
}
//-----------------------------------------------------------------------------
bool KMAcctImap::makeConnection()
{
if (mSlave) return TRUE;
if(mAskAgain || mPasswd.isEmpty() || mLogin.isEmpty())
{
QString passwd = decryptStr(mPasswd);
bool b = FALSE;
if (KIO::PasswordDialog::getNameAndPassword(mLogin, passwd, &b,
i18n("You need to supply a username and a password to access this "
"mailbox."), FALSE, QString::null, mName, i18n("Account:"))
!= QDialog::Accepted)
{
emit finishedCheck(false);
return FALSE;
} else mPasswd = encryptStr(passwd);
}
initSlaveConfig();
mSlave = KIO::Scheduler::getConnectedSlave(getUrl(), mSlaveConfig);
if (!mSlave)
{
KMessageBox::error(0, QString("Could not start process for %1.")
.arg(getUrl().protocol()));
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------------
void KMAcctImap::slotSlaveError(KIO::Slave *aSlave, int errorCode,
const QString &errorMsg)
{
if (aSlave != mSlave) return;
if (errorCode == KIO::ERR_SLAVE_DIED) slaveDied();
if (errorCode == KIO::ERR_COULD_NOT_LOGIN && !mStorePasswd) mAskAgain = TRUE;
KMessageBox::error(0, KIO::buildErrorString(errorCode, errorMsg));
killAllJobs();
}
//-----------------------------------------------------------------------------
void KMAcctImap::displayProgress()
{
if (mProgressEnabled == mapJobData.isEmpty())
{
mProgressEnabled = !mapJobData.isEmpty();
KMBroadcastStatus::instance()->setStatusProgressEnable( mProgressEnabled );
if (!mProgressEnabled) kernel->filterMgr()->cleanup();
}
mIdle = FALSE;
if (mapJobData.isEmpty())
mIdleTimer.start(15000);
else
mIdleTimer.stop();
int total = 0, done = 0;
for (QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
it != mapJobData.end(); it++)
{
total += (*it).total;
done += (*it).done;
}
if (total == 0)
{
mTotal = 0;
return;
}
if (total > mTotal) mTotal = total;
done += mTotal - total;
KMBroadcastStatus::instance()->setStatusProgressPercent( 100*done / mTotal );
}
//-----------------------------------------------------------------------------
void KMAcctImap::slotIdleTimeout()
{
if (mIdle)
{
if (mSlave) KIO::Scheduler::disconnectSlave(mSlave);
mSlave = NULL;
mIdleTimer.stop();
} else {
if (mSlave)
{
KIO::SimpleJob *job = KIO::special(getUrl(), QCString("NOOP"), FALSE);
KIO::Scheduler::assignJobToSlave(mSlave, job);
connect(job, SIGNAL(result(KIO::Job *)),
this, SLOT(slotSimpleResult(KIO::Job *)));
}
else mIdleTimer.stop();
}
}
//-----------------------------------------------------------------------------
void KMAcctImap::slotAbortRequested()
{
killAllJobs();
}
//-----------------------------------------------------------------------------
void KMAcctImap::killAllJobs()
{
QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
for (it = mapJobData.begin(); it != mapJobData.end(); it++)
if ((*it).parent)
{
KMFolderImap *fld = (*it).parent;
fld->setContentState(KMFolderImap::imapNoInformation);
fld->setSubfolderState(KMFolderImap::imapNoInformation);
fld->sendFolderComplete(FALSE);
fld->quiet(FALSE);
}
if (mSlave && mapJobData.begin() != mapJobData.end())
{
mSlave->kill();
mSlave = NULL;
}
mapJobData.clear();
mJobList.setAutoDelete(true);
mJobList.clear();
mJobList.setAutoDelete(false);
displayProgress();
}
//-----------------------------------------------------------------------------
void KMAcctImap::killJobsForItem(KMFolderTreeItem * fti)
{
QMap<KIO::Job *, jobData>::Iterator it = mapJobData.begin();
while (it != mapJobData.end())
{
if (it.data().parent == fti->folder)
{
killAllJobs();
break;
}
else it++;
}
}
//-----------------------------------------------------------------------------
void KMAcctImap::slotSimpleResult(KIO::Job * job)
{
QMap<KIO::Job *, jobData>::Iterator it = mapJobData.find(job);
bool quiet = FALSE;
if (it != mapJobData.end())
{
quiet = (*it).quiet;
mapJobData.remove(it);
}
if (job->error())
{
if (!quiet) job->showErrorDialog();
if (job->error() == KIO::ERR_SLAVE_DIED) slaveDied();
}
displayProgress();
}
//-----------------------------------------------------------------------------
void KMAcctImap::processNewMail(bool interactive)
{
if (!mFolder || !mFolder->child())
{
emit finishedCheck(false);
return;
}
QStringList strList;
QValueList<QGuardedPtr<KMFolder> > folderList;
kernel->imapFolderMgr()->createFolderList(&strList, &folderList,
mFolder->child(), QString::null, false);
QValueList<QGuardedPtr<KMFolder> >::Iterator it;
for (it = folderList.begin(); it != folderList.end(); it++)
{
KMFolder *folder = *it;
if (folder && !folder->noContent())
{
KMFolderImap *imapFolder = static_cast<KMFolderImap*>(folder);
if (imapFolder->getContentState() != KMFolderImap::imapInProgress)
{
if (imapFolder->isSelected())
imapFolder->getFolder();
else imapFolder->processNewMail(interactive);
}
}
}
emit finishedCheck(false);
}