00001
00002 #include <config.h>
00003
00004 #include "kmaccount.h"
00005
00006 #include "kmacctmgr.h"
00007 #include "kmacctfolder.h"
00008 #include "kmfoldermgr.h"
00009 #include "kmfiltermgr.h"
00010 #include "messagesender.h"
00011 #include "kmkernel.h"
00012 #include "broadcaststatus.h"
00013 using KPIM::BroadcastStatus;
00014 #include "kmfoldercachedimap.h"
00015
00016 #include "progressmanager.h"
00017 using KPIM::ProgressItem;
00018 using KPIM::ProgressManager;
00019
00020 using KMail::FolderJob;
00021
00022 #include <kapplication.h>
00023 #include <klocale.h>
00024 #include <kmessagebox.h>
00025 #include <kdebug.h>
00026 #include <kconfig.h>
00027
00028 #include <qeventloop.h>
00029
00030 #include <stdlib.h>
00031 #include <unistd.h>
00032 #include <errno.h>
00033
00034 #include <assert.h>
00035
00036
00037 #include "kmaccount.moc"
00038
00039
00040 KMPrecommand::KMPrecommand(const QString &precommand, QObject *parent)
00041 : QObject(parent), mPrecommand(precommand)
00042 {
00043 BroadcastStatus::instance()->setStatusMsg(
00044 i18n("Executing precommand %1").arg(precommand ));
00045
00046 mPrecommandProcess.setUseShell(true);
00047 mPrecommandProcess << precommand;
00048
00049 connect(&mPrecommandProcess, SIGNAL(processExited(KProcess *)),
00050 SLOT(precommandExited(KProcess *)));
00051 }
00052
00053
00054 KMPrecommand::~KMPrecommand()
00055 {
00056 }
00057
00058
00059
00060 bool KMPrecommand::start()
00061 {
00062 bool ok = mPrecommandProcess.start( KProcess::NotifyOnExit );
00063 if (!ok) KMessageBox::error(0, i18n("Could not execute precommand '%1'.")
00064 .arg(mPrecommand));
00065 return ok;
00066 }
00067
00068
00069
00070 void KMPrecommand::precommandExited(KProcess *p)
00071 {
00072 int exitCode = p->normalExit() ? p->exitStatus() : -1;
00073 if (exitCode)
00074 KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2")
00075 .arg(exitCode).arg(strerror(exitCode)));
00076 emit finished(!exitCode);
00077 }
00078
00079
00080
00081 KMAccount::KMAccount(KMAcctMgr* aOwner, const QString& aName, uint id)
00082 : KAccount( id, aName ),
00083 mTrash(KMKernel::self()->trashFolder()->idString()),
00084 mOwner(aOwner),
00085 mFolder(0),
00086 mTimer(0),
00087 mInterval(0),
00088 mExclude(false),
00089 mCheckingMail(false),
00090 mPrecommandSuccess(true),
00091 mHasInbox(false),
00092 mMailCheckProgressItem(0)
00093 {
00094 assert(aOwner != 0);
00095
00096 connect(&mReceiptTimer,SIGNAL(timeout()),SLOT(sendReceipts()));
00097 }
00098
00099 void KMAccount::init() {
00100 mTrash = kmkernel->trashFolder()->idString();
00101 mExclude = false;
00102 mInterval = 0;
00103 mNewInFolder.clear();
00104 }
00105
00106
00107 KMAccount::~KMAccount()
00108 {
00109 if (!kmkernel->shuttingDown() && mFolder) mFolder->removeAccount(this);
00110 if (mTimer) deinstallTimer();
00111 }
00112
00113
00114
00115 void KMAccount::setName(const QString& aName)
00116 {
00117 mName = (aName.isEmpty()) ? i18n("Unnamed") : aName;
00118 }
00119
00120
00121
00122 void KMAccount::clearPasswd()
00123 {
00124 }
00125
00126
00127
00128 void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
00129 {
00130 if(!aFolder) {
00131
00132 mFolder = 0;
00133 return;
00134 }
00135 mFolder = (KMAcctFolder*)aFolder;
00136 if (addAccount) mFolder->addAccount(this);
00137 }
00138
00139
00140
00141 void KMAccount::readConfig(KConfig& config)
00142 {
00143 QString folderName;
00144 mFolder = 0;
00145 folderName = config.readEntry("Folder");
00146 setCheckInterval(config.readNumEntry("check-interval", 0));
00147 setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString()));
00148 setCheckExclude(config.readBoolEntry("check-exclude", false));
00149 setPrecommand(config.readPathEntry("precommand"));
00150
00151 if (!folderName.isEmpty())
00152 {
00153 setFolder(kmkernel->folderMgr()->findIdString(folderName), true);
00154 }
00155
00156 if (mInterval == 0)
00157 deinstallTimer();
00158 else
00159 installTimer();
00160 }
00161
00162
00163
00164 void KMAccount::writeConfig(KConfig& config)
00165 {
00166
00167 KAccount::writeConfig(config);
00168
00169 config.writeEntry("Type", type());
00170 config.writeEntry("Folder", mFolder ? mFolder->idString() : QString::null);
00171 config.writeEntry("check-interval", mInterval);
00172 config.writeEntry("check-exclude", mExclude);
00173 config.writePathEntry("precommand", mPrecommand);
00174 config.writeEntry("trash", mTrash);
00175 }
00176
00177
00178
00179 void KMAccount::sendReceipt(KMMessage* aMsg)
00180 {
00181 KConfig* cfg = KMKernel::config();
00182 bool sendReceipts;
00183
00184 KConfigGroupSaver saver(cfg, "General");
00185
00186 sendReceipts = cfg->readBoolEntry("send-receipts", false);
00187 if (!sendReceipts) return;
00188
00189 KMMessage *newMsg = aMsg->createDeliveryReceipt();
00190 if (newMsg) {
00191 mReceipts.append(newMsg);
00192 mReceiptTimer.start(0,true);
00193 }
00194 }
00195
00196
00197
00198 bool KMAccount::processNewMsg(KMMessage* aMsg)
00199 {
00200 int rc, processResult;
00201
00202 assert(aMsg != 0);
00203
00204
00205 KMFolderCachedImap* parent = 0;
00206 if( type() == "cachedimap" )
00207 parent = static_cast<KMFolderCachedImap*>( aMsg->storage() );
00208
00209
00210
00211 sendReceipt(aMsg);
00212
00213
00214
00215
00216 if ( type() != "cachedimap" && type() != "imap" ) {
00217 if ( aMsg->isOld() )
00218 aMsg->setStatus(KMMsgStatusUnread);
00219
00220 else
00221 aMsg->setStatus(KMMsgStatusNew);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 processResult = kmkernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound);
00234 if (processResult == 2) {
00235 perror("Critical error: Unable to collect mail (out of space?)");
00236 KMessageBox::information(0,(i18n("Critical error: "
00237 "Unable to collect mail: ")) + QString::fromLocal8Bit(strerror(errno)));
00238 return false;
00239 }
00240 else if (processResult == 1)
00241 {
00242 if( type() == "cachedimap" )
00243 ;
00244 else {
00245
00246
00247 kmkernel->filterMgr()->tempOpenFolder(mFolder);
00248 rc = mFolder->addMsg(aMsg);
00249
00250
00251
00252
00253
00254
00255
00256
00257 if (rc) {
00258 perror("failed to add message");
00259 KMessageBox::information(0, i18n("Failed to add message:\n") +
00260 QString(strerror(rc)));
00261 return false;
00262 }
00263 int count = mFolder->count();
00264
00265 if (count != 1) mFolder->unGetMsg(count - 1);
00266 }
00267 }
00268
00269
00270 QString folderId;
00271 if ( processResult == 1 ) {
00272 folderId = ( type() == "cachedimap" ) ? parent->folder()->idString()
00273 : mFolder->idString();
00274 }
00275 else {
00276 folderId = aMsg->parent()->idString();
00277 }
00278 addToNewInFolder( folderId, 1 );
00279
00280 return true;
00281 }
00282
00283
00284
00285 void KMAccount::setCheckInterval(int aInterval)
00286 {
00287 if (aInterval <= 0)
00288 mInterval = 0;
00289 else
00290 mInterval = aInterval;
00291
00292 }
00293
00294 int KMAccount::checkInterval() const
00295 {
00296 if ( mInterval <= 0 )
00297 return mInterval;
00298 return QMAX( mInterval, GlobalSettings::self()->minimumCheckInterval() );
00299 }
00300
00301
00302 void KMAccount::deleteFolderJobs()
00303 {
00304 mJobList.setAutoDelete(true);
00305 mJobList.clear();
00306 mJobList.setAutoDelete(false);
00307 }
00308
00309
00310 void KMAccount::ignoreJobsForMessage( KMMessage* msg )
00311 {
00312
00313 for( QPtrListIterator<FolderJob> it(mJobList); it.current(); ++it ) {
00314 if ( it.current()->msgList().first() == msg) {
00315 FolderJob *job = it.current();
00316 mJobList.remove( job );
00317 delete job;
00318 break;
00319 }
00320 }
00321 }
00322
00323
00324 void KMAccount::setCheckExclude(bool aExclude)
00325 {
00326 mExclude = aExclude;
00327 }
00328
00329
00330
00331 void KMAccount::installTimer()
00332 {
00333 if (mInterval <= 0) return;
00334 if(!mTimer)
00335 {
00336 mTimer = new QTimer();
00337 connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck()));
00338 }
00339 else
00340 {
00341 mTimer->stop();
00342 }
00343 mTimer->start( checkInterval() * 60000 );
00344 }
00345
00346
00347
00348 void KMAccount::deinstallTimer()
00349 {
00350 delete mTimer;
00351 mTimer = 0;
00352 }
00353
00354
00355 bool KMAccount::runPrecommand(const QString &precommand)
00356 {
00357
00358 if ( precommand.isEmpty() )
00359 return true;
00360
00361 KMPrecommand precommandProcess(precommand, this);
00362
00363 BroadcastStatus::instance()->setStatusMsg(
00364 i18n("Executing precommand %1").arg(precommand ));
00365
00366 connect(&precommandProcess, SIGNAL(finished(bool)),
00367 SLOT(precommandExited(bool)));
00368
00369 kdDebug(5006) << "Running precommand " << precommand << endl;
00370 if (!precommandProcess.start()) return false;
00371
00372 kapp->eventLoop()->enterLoop();
00373
00374 return mPrecommandSuccess;
00375 }
00376
00377
00378 void KMAccount::precommandExited(bool success)
00379 {
00380 mPrecommandSuccess = success;
00381 kapp->eventLoop()->exitLoop();
00382 }
00383
00384
00385 void KMAccount::mailCheck()
00386 {
00387 if (mTimer)
00388 mTimer->stop();
00389 kmkernel->acctMgr()->singleCheckMail(this, false);
00390 }
00391
00392
00393 void KMAccount::sendReceipts()
00394 {
00395 QValueList<KMMessage*>::Iterator it;
00396 for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
00397 kmkernel->msgSender()->send(*it);
00398 mReceipts.clear();
00399 }
00400
00401
00402 QString KMAccount::encryptStr(const QString &aStr)
00403 {
00404 QString result;
00405 for (uint i = 0; i < aStr.length(); i++)
00406 result += (aStr[i].unicode() < 0x20) ? aStr[i] :
00407 QChar(0x1001F - aStr[i].unicode());
00408 return result;
00409 }
00410
00411
00412 QString KMAccount::importPassword(const QString &aStr)
00413 {
00414 unsigned int i, val;
00415 unsigned int len = aStr.length();
00416 QCString result;
00417 result.resize(len+1);
00418
00419 for (i=0; i<len; i++)
00420 {
00421 val = aStr[i] - ' ';
00422 val = (255-' ') - val;
00423 result[i] = (char)(val + ' ');
00424 }
00425 result[i] = '\0';
00426
00427 return encryptStr(result);
00428 }
00429
00430 void KMAccount::invalidateIMAPFolders()
00431 {
00432
00433 }
00434
00435 void KMAccount::pseudoAssign( const KMAccount * a ) {
00436 if ( !a ) return;
00437
00438 setName( a->name() );
00439 setId( a->id() );
00440 setCheckInterval( a->checkInterval() );
00441 setCheckExclude( a->checkExclude() );
00442 setFolder( a->folder() );
00443 setPrecommand( a->precommand() );
00444 setTrash( a->trash() );
00445 }
00446
00447
00448 void KMAccount::checkDone( bool newmail, CheckStatus status )
00449 {
00450 mCheckingMail = false;
00451
00452
00453 if (mTimer)
00454 mTimer->start( checkInterval() * 60000 );
00455 if ( mMailCheckProgressItem ) {
00456 mMailCheckProgressItem->setComplete();
00457 mMailCheckProgressItem = 0;
00458 }
00459
00460 emit newMailsProcessed( mNewInFolder );
00461 emit finishedCheck( newmail, status );
00462 mNewInFolder.clear();
00463 }
00464
00465
00466 void KMAccount::addToNewInFolder( QString folderId, int num )
00467 {
00468 if ( mNewInFolder.find( folderId ) == mNewInFolder.end() )
00469 mNewInFolder[folderId] = num;
00470 else
00471 mNewInFolder[folderId] += num;
00472 }