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