kmail Library API Documentation

kmkernel.cpp

00001 /* -*- mode: C++; c-file-style: "gnu" -*- */ 00002 #ifdef HAVE_CONFIG_H 00003 #include <config.h> 00004 #endif 00005 00006 #include "config.h" 00007 #include "kmkernel.h" 00008 00009 #include <weaver.h> 00010 #include <weaverlogger.h> 00011 00012 #include "globalsettings.h" 00013 #include "kmstartup.h" 00014 #include "kmmsgindex.h" 00015 #include "kmmainwin.h" 00016 #include "kmcomposewin.h" 00017 #include "kmfoldermgr.h" 00018 #include "kmfoldercachedimap.h" 00019 #include "kmacctcachedimap.h" 00020 #include "kmfiltermgr.h" 00021 #include "kmfilteraction.h" 00022 #include "kmsender.h" 00023 #include "undostack.h" 00024 #include "kmacctmgr.h" 00025 #include <libkdepim/kfileio.h> 00026 #include "kmversion.h" 00027 #include "kmreaderwin.h" 00028 #include "kmmainwidget.h" 00029 #include "kmfoldertree.h" 00030 #include "recentaddresses.h" 00031 using KRecentAddress::RecentAddresses; 00032 #include "kmmsgdict.h" 00033 #include <libkpimidentities/identity.h> 00034 #include <libkpimidentities/identitymanager.h> 00035 #include "configuredialog.h" 00036 #include "kmcommands.h" 00037 #include "kmsystemtray.h" 00038 // #### disabled for now #include "startupwizard.h" 00039 00040 00041 #include <kwin.h> 00042 #include "kmgroupware.h" 00043 #include "kmailicalifaceimpl.h" 00044 #include "mailserviceimpl.h" 00045 using KMail::MailServiceImpl; 00046 #include "folderIface.h" 00047 using KMail::FolderIface; 00048 #include "jobscheduler.h" 00049 00050 #include <kapplication.h> 00051 #include <kaboutdata.h> 00052 #include <kmessagebox.h> 00053 #include <knotifyclient.h> 00054 #include <kstaticdeleter.h> 00055 #include <kstandarddirs.h> 00056 #include <kconfig.h> 00057 #include <kprogress.h> 00058 #include <kpassivepopup.h> 00059 #include <dcopclient.h> 00060 #include <ksystemtray.h> 00061 #include <kpgp.h> 00062 #include <kdebug.h> 00063 00064 #include <qutf7codec.h> 00065 #include <qvbox.h> 00066 #include <qdir.h> 00067 #include <qwidgetlist.h> 00068 #include <qobjectlist.h> 00069 00070 #include <sys/types.h> 00071 #include <dirent.h> 00072 #include <sys/stat.h> 00073 #include <unistd.h> 00074 #include <stdio.h> 00075 #include <stdlib.h> 00076 #include <assert.h> 00077 00078 #include <X11/Xlib.h> 00079 #include <fixx11h.h> 00080 #include <kcmdlineargs.h> 00081 #include <kstartupinfo.h> 00082 00083 KMKernel *KMKernel::mySelf = 0; 00084 00085 /********************************************************************/ 00086 /* Constructor and destructor */ 00087 /********************************************************************/ 00088 KMKernel::KMKernel (QObject *parent, const char *name) : 00089 DCOPObject("KMailIface"), QObject(parent, name), 00090 mIdentityManager(0), mConfigureDialog(0), 00091 mContextMenuShown( false ) 00092 { 00093 kdDebug(5006) << "KMKernel::KMKernel" << endl; 00094 mySelf = this; 00095 the_startingUp = true; 00096 closed_by_user = true; 00097 the_firstInstance = true; 00098 the_msgDict = 0; 00099 the_msgIndex = 0; 00100 00101 the_inboxFolder = 0; 00102 the_outboxFolder = 0; 00103 the_sentFolder = 0; 00104 the_trashFolder = 0; 00105 the_draftsFolder = 0; 00106 00107 the_folderMgr = 0; 00108 the_imapFolderMgr = 0; 00109 the_dimapFolderMgr = 0; 00110 the_searchFolderMgr = 0; 00111 the_undoStack = 0; 00112 the_acctMgr = 0; 00113 the_filterMgr = 0; 00114 the_popFilterMgr = 0; 00115 the_filterActionDict = 0; 00116 the_msgSender = 0; 00117 mWin = 0; 00118 mMailCheckAborted = false; 00119 00120 // make sure that we check for config updates before doing anything else 00121 KMKernel::config(); 00122 // this shares the kmailrc parsing too (via KSharedConfig), and reads values from it 00123 // so better do it here, than in some code where changing the group of config() 00124 // would be unexpected 00125 GlobalSettings::self(); 00126 00127 mGroupware = new KMGroupware( this ); 00128 00129 // Set up DCOP interface 00130 mICalIface = new KMailICalIfaceImpl(); 00131 00132 mJobScheduler = new JobScheduler( this ); 00133 00134 mXmlGuiInstance = 0; 00135 mDeadLetterTimer = new QTimer( this ); 00136 connect( mDeadLetterTimer, SIGNAL(timeout()), SLOT(dumpDeadLetters()) ); 00137 mDeadLetterInterval = 1000*120; // 2 minutes 00138 00139 new Kpgp::Module(); 00140 00141 // register our own (libkdenetwork) utf-7 codec as long as Qt 00142 // doesn't have it's own: 00143 if ( !QTextCodec::codecForName("utf-7") ) { 00144 kdDebug(5006) << "No Qt-native utf-7 codec found; registering QUtf7Codec from libkdenetwork" << endl; 00145 (void) new QUtf7Codec(); 00146 } 00147 00148 // In the case of Japan. Japanese locale name is "eucjp" but 00149 // The Japanese mail systems normally used "iso-2022-jp" of locale name. 00150 // We want to change locale name from eucjp to iso-2022-jp at KMail only. 00151 if ( QCString(QTextCodec::codecForLocale()->name()).lower() == "eucjp" ) 00152 { 00153 netCodec = QTextCodec::codecForName("jis7"); 00154 // QTextCodec *cdc = QTextCodec::codecForName("jis7"); 00155 // QTextCodec::setCodecForLocale(cdc); 00156 // KGlobal::locale()->setEncoding(cdc->mibEnum()); 00157 } else { 00158 netCodec = QTextCodec::codecForLocale(); 00159 } 00160 mMailService = new MailServiceImpl(); 00161 00162 connectDCOPSignal( 0, 0, "kmailSelectFolder(QString)", 00163 "selectFolder(QString)", false ); 00164 } 00165 00166 KMKernel::~KMKernel () 00167 { 00168 QMap<KIO::Job*, putData>::Iterator it = mPutJobs.begin(); 00169 while ( it != mPutJobs.end() ) 00170 { 00171 KIO::Job *job = it.key(); 00172 mPutJobs.remove( it ); 00173 job->kill(); 00174 it = mPutJobs.begin(); 00175 } 00176 00177 delete mICalIface; 00178 mICalIface = 0; 00179 delete mMailService; 00180 mMailService = 0; 00181 00182 GlobalSettings::writeConfig(); 00183 mySelf = 0; 00184 kdDebug(5006) << "KMKernel::~KMKernel" << endl; 00185 } 00186 00187 bool KMKernel::handleCommandLine( bool noArgsOpensReader ) 00188 { 00189 QString to, cc, bcc, subj, body; 00190 KURL messageFile; 00191 KURL::List attachURLs; 00192 bool mailto = false; 00193 bool checkMail = false; 00194 bool viewOnly = false; 00195 00196 // process args: 00197 KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); 00198 if (args->getOption("subject")) 00199 { 00200 mailto = true; 00201 subj = QString::fromLocal8Bit(args->getOption("subject")); 00202 } 00203 00204 if (args->getOption("cc")) 00205 { 00206 mailto = true; 00207 cc = QString::fromLocal8Bit(args->getOption("cc")); 00208 } 00209 00210 if (args->getOption("bcc")) 00211 { 00212 mailto = true; 00213 bcc = QString::fromLocal8Bit(args->getOption("bcc")); 00214 } 00215 00216 if (args->getOption("msg")) 00217 { 00218 mailto = true; 00219 messageFile.setPath( QString::fromLocal8Bit(args->getOption("msg")) ); 00220 } 00221 00222 if (args->getOption("body")) 00223 { 00224 mailto = true; 00225 body = QString::fromLocal8Bit(args->getOption("body")); 00226 } 00227 00228 QCStringList attachList = args->getOptionList("attach"); 00229 if (!attachList.isEmpty()) 00230 { 00231 mailto = true; 00232 for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it ) 00233 if ( !(*it).isEmpty() ) 00234 attachURLs += KURL( QString::fromLocal8Bit( *it ) ); 00235 } 00236 00237 if (args->isSet("composer")) 00238 mailto = true; 00239 00240 if (args->isSet("check")) 00241 checkMail = true; 00242 00243 if ( args->getOption( "view" ) ) { 00244 viewOnly = true; 00245 const QString filename = 00246 QString::fromLocal8Bit( args->getOption( "view" ) ); 00247 messageFile = KURL::fromPathOrURL( filename ); 00248 if ( !messageFile.isValid() ) { 00249 messageFile = KURL(); 00250 messageFile.setPath( filename ); 00251 } 00252 } 00253 00254 for(int i= 0; i < args->count(); i++) 00255 { 00256 if (strncasecmp(args->arg(i),"mailto:",7)==0) 00257 to += args->url(i).path() + ", "; 00258 else { 00259 QString tmpArg = QString::fromLocal8Bit( args->arg(i) ); 00260 KURL url( tmpArg ); 00261 if ( url.isValid() ) 00262 attachURLs += url; 00263 else 00264 to += tmpArg + ", "; 00265 } 00266 mailto = true; 00267 } 00268 if ( !to.isEmpty() ) { 00269 // cut off the superfluous trailing ", " 00270 to.truncate( to.length() - 2 ); 00271 } 00272 00273 args->clear(); 00274 00275 if ( !noArgsOpensReader && !mailto && !checkMail && !viewOnly ) 00276 return false; 00277 00278 if ( viewOnly ) 00279 viewMessage( messageFile ); 00280 else 00281 action( mailto, checkMail, to, cc, bcc, subj, body, messageFile, 00282 attachURLs ); 00283 return true; 00284 } 00285 00286 /********************************************************************/ 00287 /* DCOP-callable, and command line actions */ 00288 /********************************************************************/ 00289 void KMKernel::checkMail () //might create a new reader but won't show!! 00290 { 00291 kmkernel->acctMgr()->checkMail(false); 00292 } 00293 00294 QStringList KMKernel::accounts() 00295 { 00296 return kmkernel->acctMgr()->getAccounts(); 00297 } 00298 00299 void KMKernel::checkAccount (const QString &account) //might create a new reader but won't show!! 00300 { 00301 kdDebug(5006) << "KMKernel::checkMail called" << endl; 00302 00303 KMAccount* acct = kmkernel->acctMgr()->findByName(account); 00304 if (acct) 00305 kmkernel->acctMgr()->singleCheckMail(acct, false); 00306 } 00307 00308 void KMKernel::openReader( bool onlyCheck ) 00309 { 00310 KMMainWin *mWin = 0; 00311 KMainWindow *ktmw = 0; 00312 kdDebug(5006) << "KMKernel::openReader called" << endl; 00313 00314 if (KMainWindow::memberList) 00315 for (ktmw = KMainWindow::memberList->first(); ktmw; 00316 ktmw = KMainWindow::memberList->next()) 00317 if (ktmw->isA("KMMainWin")) 00318 break; 00319 00320 bool activate; 00321 if (ktmw) { 00322 mWin = (KMMainWin *) ktmw; 00323 activate = !onlyCheck; // existing window: only activate if not --check 00324 } 00325 else { 00326 mWin = new KMMainWin; 00327 activate = true; // new window: always activate 00328 } 00329 00330 if ( activate ) { 00331 mWin->show(); 00332 // Activate window - doing this instead of KWin::activateWindow(mWin->winId()); 00333 // so that it also works when called from KMailApplication::newInstance() 00334 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00335 KStartupInfo::setNewStartupId( mWin, kapp->startupId() ); 00336 #endif 00337 } 00338 } 00339 00340 int KMKernel::openComposer (const QString &to, const QString &cc, 00341 const QString &bcc, const QString &subject, 00342 const QString &body, int hidden, 00343 const KURL &messageFile, 00344 const KURL::List &attachURLs) 00345 { 00346 kdDebug(5006) << "KMKernel::openComposer called" << endl; 00347 00348 KMMessage *msg = new KMMessage; 00349 msg->initHeader(); 00350 msg->setCharset("utf-8"); 00351 if (!cc.isEmpty()) msg->setCc(cc); 00352 if (!bcc.isEmpty()) msg->setBcc(bcc); 00353 if (!subject.isEmpty()) msg->setSubject(subject); 00354 if (!to.isEmpty()) msg->setTo(to); 00355 00356 if (!messageFile.isEmpty() && messageFile.isLocalFile()) { 00357 QCString str = KPIM::kFileToString( messageFile.path(), true, false ); 00358 if( !str.isEmpty() ) 00359 msg->setBody( QString::fromLocal8Bit( str ).utf8() ); 00360 } 00361 else if (!body.isEmpty()) 00362 msg->setBody(body.utf8()); 00363 00364 KMComposeWin *cWin = new KMComposeWin(msg); 00365 cWin->setCharset("", TRUE); 00366 for ( KURL::List::ConstIterator it = attachURLs.begin() ; it != attachURLs.end() ; ++it ) 00367 cWin->addAttach((*it)); 00368 if (hidden == 0) { 00369 cWin->show(); 00370 // Activate window - doing this instead of KWin::activateWindow(cWin->winId()); 00371 // so that it also works when called from KMailApplication::newInstance() 00372 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00373 KStartupInfo::setNewStartupId( cWin, kapp->startupId() ); 00374 #endif 00375 } 00376 return 1; 00377 } 00378 00379 00380 int KMKernel::openComposer (const QString &to, const QString &cc, 00381 const QString &bcc, const QString &subject, 00382 const QString &body, int hidden, 00383 const QString &attachName, 00384 const QCString &attachCte, 00385 const QCString &attachData, 00386 const QCString &attachType, 00387 const QCString &attachSubType, 00388 const QCString &attachParamAttr, 00389 const QString &attachParamValue, 00390 const QCString &attachContDisp ) 00391 { 00392 kdDebug(5006) << "KMKernel::openComposer called (deprecated version)" << endl; 00393 00394 return openComposer ( to, cc, bcc, subject, body, hidden, 00395 attachName, attachCte, attachData, 00396 attachType, attachSubType, attachParamAttr, 00397 attachParamValue, attachContDisp, QCString() ); 00398 } 00399 00400 int KMKernel::openComposer (const QString &to, const QString &cc, 00401 const QString &bcc, const QString &subject, 00402 const QString &body, int hidden, 00403 const QString &attachName, 00404 const QCString &attachCte, 00405 const QCString &attachData, 00406 const QCString &attachType, 00407 const QCString &attachSubType, 00408 const QCString &attachParamAttr, 00409 const QString &attachParamValue, 00410 const QCString &attachContDisp, 00411 const QCString &attachCharset ) 00412 { 00413 kdDebug(5006) << "KMKernel::openComposer()" << endl; 00414 00415 KMMessage *msg = new KMMessage; 00416 KMMessagePart *msgPart = 0; 00417 msg->initHeader(); 00418 msg->setCharset( "utf-8" ); 00419 if ( !cc.isEmpty() ) msg->setCc(cc); 00420 if ( !bcc.isEmpty() ) msg->setBcc(bcc); 00421 if ( !subject.isEmpty() ) msg->setSubject(subject); 00422 if ( !to.isEmpty() ) msg->setTo(to); 00423 if ( !body.isEmpty() ) msg->setBody(body.utf8()); 00424 00425 bool iCalAutoSend = false; 00426 KConfigGroup options( config(), "Groupware" ); 00427 if ( !attachData.isEmpty() ) { 00428 if ( attachName == "cal.ics" && attachType == "text" && 00429 attachSubType == "calendar" && attachParamAttr == "method" && 00430 options.readBoolEntry( "LegacyBodyInvites", false ) ) { 00431 // KOrganizer invitation caught and to be sent as body instead 00432 msg->setBody( attachData ); 00433 msg->setHeaderField( "Content-Type", 00434 QString( "text/calendar; method=%1; " 00435 "charset=\"utf-8\"" ). 00436 arg( attachParamValue ) ); 00437 00438 // Don't show the composer window, if the automatic sending is checked 00439 iCalAutoSend = options.readBoolEntry( "AutomaticSending", true ); 00440 } else { 00441 // Just do what we're told to do 00442 msgPart = new KMMessagePart; 00443 msgPart->setName( attachName ); 00444 msgPart->setCteStr( attachCte ); 00445 msgPart->setBodyEncoded( attachData ); 00446 msgPart->setTypeStr( attachType ); 00447 msgPart->setSubtypeStr( attachSubType ); 00448 msgPart->setParameter( attachParamAttr, attachParamValue ); 00449 msgPart->setContentDisposition( attachContDisp ); 00450 if( !attachCharset.isEmpty() ) { 00451 // kdDebug(5006) << "KMKernel::openComposer set attachCharset to " 00452 // << attachCharset << endl; 00453 msgPart->setCharset( attachCharset ); 00454 } 00455 } 00456 } 00457 00458 KMComposeWin *cWin = new KMComposeWin( msg ); 00459 cWin->setAutoDelete( true ); 00460 if( iCalAutoSend ) 00461 cWin->slotWordWrapToggled( false ); 00462 else 00463 cWin->setCharset( "", true ); 00464 if ( msgPart ) 00465 cWin->addAttach(msgPart); 00466 00467 if ( hidden == 0 && !iCalAutoSend ) { 00468 cWin->show(); 00469 // Activate window - doing this instead of KWin::activateWindow(cWin->winId()); 00470 // so that it also works when called from KMailApplication::newInstance() 00471 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00472 KStartupInfo::setNewStartupId( cWin, kapp->startupId() ); 00473 #endif 00474 } else { 00475 cWin->setAutoDeleteWindow( true ); 00476 cWin->slotSendNow(); 00477 } 00478 00479 return 1; 00480 } 00481 00482 DCOPRef KMKernel::openComposer(const QString &to, const QString &cc, 00483 const QString &bcc, const QString &subject, 00484 const QString &body,bool hidden) 00485 { 00486 KMMessage *msg = new KMMessage; 00487 msg->initHeader(); 00488 msg->setCharset("utf-8"); 00489 if (!cc.isEmpty()) msg->setCc(cc); 00490 if (!bcc.isEmpty()) msg->setBcc(bcc); 00491 if (!subject.isEmpty()) msg->setSubject(subject); 00492 if (!to.isEmpty()) msg->setTo(to); 00493 if (!body.isEmpty()) msg->setBody(body.utf8()); 00494 00495 KMComposeWin *cWin = new KMComposeWin(msg); 00496 cWin->setCharset("", TRUE); 00497 if (!hidden) { 00498 cWin->show(); 00499 // Activate window - doing this instead of KWin::activateWindow(cWin->winId()); 00500 // so that it also works when called from KMailApplication::newInstance() 00501 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00502 KStartupInfo::setNewStartupId( cWin, kapp->startupId() ); 00503 #endif 00504 } 00505 00506 return DCOPRef(cWin); 00507 } 00508 00509 DCOPRef KMKernel::newMessage() 00510 { 00511 KMFolder *folder = 0; 00512 KMMainWidget *widget = getKMMainWidget(); 00513 if ( widget && widget->folderTree() ) 00514 folder = widget->folderTree()->currentFolder(); 00515 00516 KMComposeWin *win; 00517 KMMessage *msg = new KMMessage; 00518 if ( folder ) { 00519 msg->initHeader( folder->identity() ); 00520 win = new KMComposeWin( msg, folder->identity() ); 00521 } else { 00522 msg->initHeader(); 00523 win = new KMComposeWin( msg ); 00524 } 00525 win->show(); 00526 00527 return DCOPRef( win ); 00528 } 00529 00530 int KMKernel::viewMessage( const KURL & messageFile ) 00531 { 00532 KMOpenMsgCommand *openCommand = new KMOpenMsgCommand( 0, messageFile ); 00533 00534 openCommand->start(); 00535 00536 return 1; 00537 } 00538 00539 int KMKernel::sendCertificate( const QString& to, const QByteArray& certData ) 00540 { 00541 KMMessage *msg = new KMMessage; 00542 msg->initHeader(); 00543 msg->setCharset("utf-8"); 00544 msg->setSubject( i18n( "Certificate Signature Request" ) ); 00545 if (!to.isEmpty()) msg->setTo(to); 00546 // ### Make this message customizable via KIOSK 00547 msg->setBody( i18n( "Please create a certificate from attachment and return to sender." ).utf8() ); 00548 00549 KMComposeWin *cWin = new KMComposeWin(msg); 00550 cWin->setCharset("", TRUE); 00551 cWin->slotSetAlwaysSend( true ); 00552 if (!certData.isEmpty()) { 00553 KMMessagePart *msgPart = new KMMessagePart; 00554 msgPart->setName("smime.p10"); 00555 msgPart->setCteStr("base64"); 00556 msgPart->setBodyEncodedBinary(certData); 00557 msgPart->setTypeStr("application"); 00558 msgPart->setSubtypeStr("pkcs10"); 00559 msgPart->setContentDisposition("attachment; filename=smime.p10"); 00560 cWin->addAttach(msgPart); 00561 } 00562 00563 cWin->show(); 00564 return 1; 00565 } 00566 00567 00568 int KMKernel::dcopAddMessage(const QString & foldername,const QString & msgUrlString) 00569 { 00570 return dcopAddMessage(foldername, KURL(msgUrlString)); 00571 } 00572 00573 int KMKernel::dcopAddMessage(const QString & foldername,const KURL & msgUrl) 00574 { 00575 if ( foldername.isEmpty() ) 00576 return -1; 00577 00578 int retval; 00579 QCString messageText; 00580 static QStringList *msgIds = 0; 00581 static QString lastFolder = ""; 00582 bool readFolderMsgIds = false; 00583 00584 //kdDebug(5006) << "KMKernel::dcopAddMessage called" << endl; 00585 00586 if ( foldername != lastFolder ) { 00587 if ( msgIds != 0 ) { 00588 delete msgIds; 00589 msgIds = 0; 00590 } 00591 msgIds = new QStringList; 00592 readFolderMsgIds = true; 00593 lastFolder = foldername; 00594 } 00595 00596 if (!msgUrl.isEmpty() && msgUrl.isLocalFile()) { 00597 00598 // This is a proposed change by Daniel Andor. 00599 // He proposed to change from the fopen(blah) 00600 // to a KPIM::kFileToString(blah). 00601 // Although it assigns a QString to a QString, 00602 // because of the implicit sharing this poses 00603 // no memory or performance penalty. 00604 00605 messageText = KPIM::kFileToString( msgUrl.path(), true, false); 00606 if ( messageText.isNull() ) 00607 return -2; 00608 00609 KMMessage *msg = new KMMessage(); 00610 msg->fromString( messageText ); 00611 00612 KMFolder *folder = the_folderMgr->findOrCreate(foldername, false); 00613 00614 if ( folder ) { 00615 if (readFolderMsgIds) { 00616 00617 // Try to determine if a message already exists in 00618 // the folder. The message id that is searched for, is 00619 // the subject line + the date. This should be quite 00620 // unique. The change that a given date with a given 00621 // subject is in the folder twice is very small. 00622 00623 // If the subject is empty, the fromStrip string 00624 // is taken. 00625 int i; 00626 00627 folder->open(); 00628 for( i=0; i<folder->count(); i++) { 00629 KMMsgBase *mb = folder->getMsgBase(i); 00630 time_t DT = mb->date(); 00631 QString dt = ctime(&DT); 00632 QString id = mb->subject(); 00633 00634 if (id.isEmpty()) 00635 id = mb->fromStrip(); 00636 if (id.isEmpty()) 00637 id = mb->toStrip(); 00638 00639 id+=dt; 00640 00641 //fprintf(stderr,"%s\n",(const char *) id); 00642 if (!id.isEmpty()) { 00643 msgIds->append(id); 00644 } 00645 } 00646 folder->close(); 00647 } 00648 00649 time_t DT = msg->date(); 00650 QString dt = ctime( &DT ); 00651 QString msgId = msg->subject(); 00652 00653 if ( msgId.isEmpty() ) 00654 msgId = msg->fromStrip(); 00655 if ( msgId.isEmpty() ) 00656 msgId = msg->toStrip(); 00657 00658 msgId += dt; 00659 00660 int k = msgIds->findIndex( msgId ); 00661 //fprintf(stderr,"find %s = %d\n",(const char *) msgId,k); 00662 00663 if ( k == -1 ) { 00664 if ( !msgId.isEmpty() ) { 00665 msgIds->append( msgId ); 00666 } 00667 if ( folder->addMsg( msg ) == 0 ) { 00668 retval = 1; 00669 } else { 00670 retval =- 2; 00671 delete msg; 00672 msg = 0; 00673 } 00674 } else { 00675 retval = -4; 00676 } 00677 } else { 00678 retval = -1; 00679 } 00680 } else { 00681 retval = -2; 00682 } 00683 return retval; 00684 } 00685 00686 QStringList KMKernel::folderList() const 00687 { 00688 QStringList folders; 00689 const QString localPrefix = i18n( "/Local" ); 00690 folders << localPrefix; 00691 the_folderMgr->getFolderURLS( folders, localPrefix ); 00692 the_imapFolderMgr->getFolderURLS( folders ); 00693 the_dimapFolderMgr->getFolderURLS( folders ); 00694 return folders; 00695 } 00696 00697 DCOPRef KMKernel::getFolder( const QString& vpath ) 00698 { 00699 const QString localPrefix = i18n( "/Local" ); 00700 if ( the_folderMgr->getFolderByURL( vpath ) ) 00701 return DCOPRef( new FolderIface( vpath ) ); 00702 else if ( vpath.startsWith( localPrefix ) && 00703 the_folderMgr->getFolderByURL( vpath.mid( localPrefix.length() ) ) ) 00704 return DCOPRef( new FolderIface( vpath.mid( localPrefix.length() ) ) ); 00705 else if ( the_imapFolderMgr->getFolderByURL( vpath ) ) 00706 return DCOPRef( new FolderIface( vpath ) ); 00707 else if ( the_dimapFolderMgr->getFolderByURL( vpath ) ) 00708 return DCOPRef( new FolderIface( vpath ) ); 00709 return DCOPRef(); 00710 } 00711 00712 bool KMKernel::showMail( Q_UINT32 serialNumber, QString /* messageId */ ) 00713 { 00714 KMMainWidget *mainWidget = 0; 00715 if (KMainWindow::memberList) { 00716 KMainWindow *win = 0; 00717 QObjectList *l; 00718 00719 // First look for a KMainWindow. 00720 for (win = KMainWindow::memberList->first(); win; 00721 win = KMainWindow::memberList->next()) { 00722 // Then look for a KMMainWidget. 00723 l = win->queryList("KMMainWidget"); 00724 if (l && l->first()) { 00725 mainWidget = dynamic_cast<KMMainWidget *>(l->first()); 00726 if (win->isActiveWindow()) 00727 break; 00728 } 00729 } 00730 } 00731 00732 if (mainWidget) { 00733 int idx = -1; 00734 KMFolder *folder = 0; 00735 msgDict()->getLocation(serialNumber, &folder, &idx); 00736 if (!folder || (idx == -1)) 00737 return false; 00738 folder->open(); 00739 KMMsgBase *msgBase = folder->getMsgBase(idx); 00740 if (!msgBase) 00741 return false; 00742 bool unGet = !msgBase->isMessage(); 00743 KMMessage *msg = folder->getMsg(idx); 00744 mainWidget->slotSelectFolder(folder); 00745 mainWidget->slotSelectMessage(msg); 00746 if (unGet) 00747 folder->unGetMsg(idx); 00748 folder->close(); 00749 return true; 00750 } 00751 00752 return false; 00753 } 00754 00755 QString KMKernel::getFrom( Q_UINT32 serialNumber ) 00756 { 00757 int idx = -1; 00758 KMFolder *folder = 0; 00759 msgDict()->getLocation(serialNumber, &folder, &idx); 00760 if (!folder || (idx == -1)) 00761 return QString::null; 00762 folder->open(); 00763 KMMsgBase *msgBase = folder->getMsgBase(idx); 00764 if (!msgBase) 00765 return QString::null; 00766 bool unGet = !msgBase->isMessage(); 00767 KMMessage *msg = folder->getMsg(idx); 00768 QString result = msg->from(); 00769 if (unGet) 00770 folder->unGetMsg(idx); 00771 folder->close(); 00772 return result; 00773 } 00774 00775 /********************************************************************/ 00776 /* Kernel methods */ 00777 /********************************************************************/ 00778 00779 void KMKernel::quit() 00780 { 00781 // Called when all windows are closed. Will take care of compacting, 00782 // sending... should handle session management too!! 00783 } 00784 /* TODO later: 00785 Asuming that: 00786 - msgsender is nonblocking 00787 (our own, QSocketNotifier based. Pops up errors and sends signal 00788 senderFinished when done) 00789 00790 o If we are getting mail, stop it (but donīt lose something!) 00791 [Done already, see mailCheckAborted] 00792 o If we are sending mail, go on UNLESS this was called by SM, 00793 in which case stop ASAP that too (can we warn? should we continue 00794 on next start?) 00795 o If we are compacting, or expunging, go on UNLESS this was SM call. 00796 In that case stop compacting ASAP and continue on next start, before 00797 touching any folders. [Not needed anymore with CompactionJob] 00798 00799 KMKernel::quit () 00800 { 00801 SM call? 00802 if compacting, stop; 00803 if sending, stop; 00804 if receiving, stop; 00805 Windows will take care of themselves (composer should dump 00806 itīs messages, if any but not in deadMail) 00807 declare us ready for the End of the Session 00808 00809 No, normal quit call 00810 All windows are off. Anything to do, should compact or sender sends? 00811 Yes, maybe put an icon in panel as a sign of life 00812 if sender sending, connect us to his finished slot, declare us ready 00813 for quit and wait for senderFinished 00814 if not, Folder manager, go compact sent-mail and outbox 00815 } (= call slotFinished()) 00816 00817 void KMKernel::slotSenderFinished() 00818 { 00819 good, Folder manager go compact sent-mail and outbox 00820 clean up stage1 (release folders and config, unregister from dcop) 00821 -- another kmail may start now --- 00822 kapp->quit(); 00823 } 00824 */ 00825 00826 00827 /********************************************************************/ 00828 /* Init, Exit, and handler methods */ 00829 /********************************************************************/ 00830 void KMKernel::testDir(const char *_name) 00831 { 00832 QString foldersPath = QDir::homeDirPath() + QString( _name ); 00833 QFileInfo info( foldersPath ); 00834 if ( !info.exists() ) { 00835 if ( ::mkdir( QFile::encodeName( foldersPath ) , S_IRWXU ) == -1 ) { 00836 KMessageBox::sorry(0, i18n("KMail could not create folder '%1';\n" 00837 "please make sure that you can view and " 00838 "modify the content of the folder '%2'.") 00839 .arg( foldersPath ).arg( QDir::homeDirPath() ) ); 00840 ::exit(-1); 00841 } 00842 } 00843 if ( !info.isDir() || !info.isReadable() || !info.isWritable() ) { 00844 KMessageBox::sorry(0, i18n("The permissions of the folder '%1' are " 00845 "incorrect;\n" 00846 "please make sure that you can view and modify " 00847 "the content of this folder.") 00848 .arg( foldersPath ) ); 00849 ::exit(-1); 00850 } 00851 } 00852 00853 00854 //----------------------------------------------------------------------------- 00855 // Open a composer for each message found in ~/dead.letter 00856 //to control 00857 void KMKernel::recoverDeadLetters(void) 00858 { 00859 KMComposeWin* win; 00860 KMMessage* msg; 00861 QDir dir = QDir::home(); 00862 QString fname = dir.path(); 00863 int i, rc, num; 00864 00865 if (!dir.exists("dead.letter")) { 00866 return; 00867 } 00868 00869 fname += "/dead.letter"; 00870 KMFolder folder(0, fname, KMFolderTypeMbox); 00871 00872 folder.setAutoCreateIndex(FALSE); 00873 rc = folder.open(); 00874 if (rc) 00875 { 00876 perror(QString("cannot open file "+fname).latin1()); 00877 return; 00878 } 00879 00880 //folder.open(); //again? 00881 00882 num = folder.count(); 00883 for (i=0; i<num; i++) 00884 { 00885 msg = folder.take(0); 00886 if (msg) 00887 { 00888 win = new KMComposeWin(); 00889 win->setMsg(msg, false, false, true); 00890 win->show(); 00891 } 00892 } 00893 folder.close(); 00894 QFile::remove(fname); 00895 } 00896 00897 void KMKernel::initFolders(KConfig* cfg) 00898 { 00899 QString name; 00900 00901 name = cfg->readEntry("inboxFolder"); 00902 00903 // Currently the folder manager cannot manage folders which are not 00904 // in the base folder directory. 00905 //if (name.isEmpty()) name = getenv("MAIL"); 00906 00907 if (name.isEmpty()) name = I18N_NOOP("inbox"); 00908 00909 the_inboxFolder = (KMFolder*)the_folderMgr->findOrCreate(name); 00910 00911 if (the_inboxFolder->canAccess() != 0) { 00912 emergencyExit( i18n("You do not have read/write permission to your inbox folder.") ); 00913 } 00914 00915 the_inboxFolder->setSystemFolder(TRUE); 00916 if ( the_inboxFolder->userWhoField().isEmpty() ) 00917 the_inboxFolder->setUserWhoField( QString::null ); 00918 // inboxFolder->open(); 00919 00920 the_outboxFolder = the_folderMgr->findOrCreate(cfg->readEntry("outboxFolder", I18N_NOOP("outbox"))); 00921 if (the_outboxFolder->canAccess() != 0) { 00922 emergencyExit( i18n("You do not have read/write permission to your outbox folder.") ); 00923 } 00924 the_outboxFolder->setNoChildren(true); 00925 00926 the_outboxFolder->setType("Out"); 00927 the_outboxFolder->setSystemFolder(TRUE); 00928 if ( the_outboxFolder->userWhoField().isEmpty() ) 00929 the_outboxFolder->setUserWhoField( QString::null ); 00930 /* Nuke the oubox's index file, to make sure that no ghost messages are in 00931 * it from a previous crash. Ghost messages happen in the outbox because it 00932 * the only folder where messages enter and leave within 5 seconds, which is 00933 * the leniency period for index invalidation. Since the number of mails in 00934 * this folder is expected to be very small, we can live with regenerating 00935 * the index on each start to be on the save side. */ 00936 //if ( the_outboxFolder->folderType() == KMFolderTypeMaildir ) 00937 // unlink( QFile::encodeName( the_outboxFolder->indexLocation() ) ); 00938 the_outboxFolder->open(); 00939 00940 the_sentFolder = the_folderMgr->findOrCreate(cfg->readEntry("sentFolder", I18N_NOOP("sent-mail"))); 00941 if (the_sentFolder->canAccess() != 0) { 00942 emergencyExit( i18n("You do not have read/write permission to your sent-mail folder.") ); 00943 } 00944 the_sentFolder->setType("St"); 00945 the_sentFolder->setSystemFolder(TRUE); 00946 if ( the_sentFolder->userWhoField().isEmpty() ) 00947 the_sentFolder->setUserWhoField( QString::null ); 00948 // the_sentFolder->open(); 00949 00950 the_trashFolder = the_folderMgr->findOrCreate(cfg->readEntry("trashFolder", I18N_NOOP("trash"))); 00951 if (the_trashFolder->canAccess() != 0) { 00952 emergencyExit( i18n("You do not have read/write permission to your trash folder.") ); 00953 } 00954 the_trashFolder->setType("Tr"); 00955 the_trashFolder->setSystemFolder(TRUE); 00956 if ( the_trashFolder->userWhoField().isEmpty() ) 00957 the_trashFolder->setUserWhoField( QString::null ); 00958 // the_trashFolder->open(); 00959 00960 the_draftsFolder = the_folderMgr->findOrCreate(cfg->readEntry("draftsFolder", I18N_NOOP("drafts"))); 00961 if (the_draftsFolder->canAccess() != 0) { 00962 emergencyExit( i18n("You do not have read/write permission to your drafts folder.") ); 00963 } 00964 the_draftsFolder->setType("Df"); 00965 the_draftsFolder->setSystemFolder(TRUE); 00966 if ( the_draftsFolder->userWhoField().isEmpty() ) 00967 the_draftsFolder->setUserWhoField( QString::null ); 00968 the_draftsFolder->open(); 00969 } 00970 00971 00972 void KMKernel::init() 00973 { 00974 QString foldersPath; 00975 KConfig* cfg; 00976 00977 the_shuttingDown = false; 00978 the_server_is_ready = false; 00979 00980 cfg = KMKernel::config(); 00981 00982 QDir dir; 00983 QString d = locateLocal("data", "kmail/"); 00984 00985 KConfigGroupSaver saver(cfg, "General"); 00986 the_firstStart = cfg->readBoolEntry("first-start", true); 00987 cfg->writeEntry("first-start", false); 00988 the_previousVersion = cfg->readEntry("previous-version"); 00989 cfg->writeEntry("previous-version", KMAIL_VERSION); 00990 foldersPath = cfg->readEntry("folders"); 00991 bool migrateMail = true; 00992 if (foldersPath.isEmpty()) 00993 { 00994 foldersPath = QDir::homeDirPath() + QString("/.Mail"); 00995 transferMail(); 00996 migrateMail = transferMailToPointMail(); 00997 if( !migrateMail) 00998 foldersPath = QDir::homeDirPath() + QString("/Mail"); 00999 } 01000 the_undoStack = new UndoStack(20); 01001 the_folderMgr = new KMFolderMgr(foldersPath); 01002 the_imapFolderMgr = new KMFolderMgr( KMFolderImap::cacheLocation(), KMImapDir); 01003 the_dimapFolderMgr = new KMFolderMgr( KMFolderCachedImap::cacheLocation(), KMDImapDir); 01004 01005 the_searchFolderMgr = new KMFolderMgr(locateLocal("data","kmail/search"), KMSearchDir); 01006 KMFolder *lsf = the_searchFolderMgr->find( i18n("Last Search") ); 01007 if (lsf) 01008 the_searchFolderMgr->remove( lsf ); 01009 01010 the_acctMgr = new KMAcctMgr(); 01011 the_filterMgr = new KMFilterMgr(); 01012 the_popFilterMgr = new KMFilterMgr(true); 01013 the_filterActionDict = new KMFilterActionDict; 01014 01015 // moved up here because KMMessage::stripOffPrefixes is used below -ta 01016 KMMessage::readConfig(); 01017 initFolders(cfg); 01018 the_acctMgr->readConfig(); 01019 the_filterMgr->readConfig(); 01020 the_popFilterMgr->readConfig(); 01021 cleanupImapFolders(); 01022 01023 the_msgSender = new KMSender; 01024 the_server_is_ready = true; 01025 01026 { // area for config group "Composer" 01027 KConfigGroupSaver saver(cfg, "Composer"); 01028 if (cfg->readListEntry("pref-charsets").isEmpty()) 01029 { 01030 cfg->writeEntry("pref-charsets", "us-ascii,iso-8859-1,locale,utf-8"); 01031 } 01032 } 01033 readConfig(); 01034 mGroupware->readConfig(); 01035 mICalIface->readConfig(); 01036 // filterMgr->dump(); 01037 #if 0 //disabled for now.. 01038 the_msgIndex = new KMMsgIndex(this, "the_index"); //create the indexer 01039 the_msgIndex->init(); 01040 the_msgIndex->remove(); 01041 delete the_msgIndex; 01042 the_msgIndex = 0; 01043 #endif 01044 01045 #if 0 01046 the_weaver = new KPIM::ThreadWeaver::Weaver( this ); 01047 the_weaverLogger = new KPIM::ThreadWeaver::WeaverThreadLogger(this); 01048 the_weaverLogger->attach (the_weaver); 01049 #endif 01050 01051 connect( the_folderMgr, SIGNAL( folderRemoved(KMFolder*) ), 01052 this, SIGNAL( folderRemoved(KMFolder*) ) ); 01053 connect( the_dimapFolderMgr, SIGNAL( folderRemoved(KMFolder*) ), 01054 this, SIGNAL( folderRemoved(KMFolder*) ) ); 01055 connect( the_imapFolderMgr, SIGNAL( folderRemoved(KMFolder*) ), 01056 this, SIGNAL( folderRemoved(KMFolder*) ) ); 01057 connect( the_searchFolderMgr, SIGNAL( folderRemoved(KMFolder*) ), 01058 this, SIGNAL( folderRemoved(KMFolder*) ) ); 01059 01060 mBackgroundTasksTimer = new QTimer( this ); 01061 connect( mBackgroundTasksTimer, SIGNAL( timeout() ), this, SLOT( slotRunBackgroundTasks() ) ); 01062 #ifdef DEBUG_SCHEDULER // for debugging, see jobscheduler.h 01063 mBackgroundTasksTimer->start( 10000, true ); // 10s minute, singleshot 01064 #else 01065 mBackgroundTasksTimer->start( 5 * 60000, true ); // 5 minutes, singleshot 01066 #endif 01067 } 01068 01069 void KMKernel::readConfig() 01070 { 01071 KConfigGroup composer( config(), "Composer" ); 01072 // default to 2 minutes, convert to ms 01073 mDeadLetterInterval = 1000 * 60 * composer.readNumEntry( "autosave", 2 ); 01074 kdDebug() << k_funcinfo << mDeadLetterInterval << endl; 01075 if ( mDeadLetterInterval ) 01076 mDeadLetterTimer->start( mDeadLetterInterval ); 01077 else 01078 mDeadLetterTimer->stop(); 01079 } 01080 01081 void KMKernel::cleanupImapFolders() 01082 { 01083 KMAccount *acct; 01084 KMFolderNode *node = the_imapFolderMgr->dir().first(); 01085 while (node) 01086 { 01087 if (node->isDir() || ((acct = the_acctMgr->find(node->id())) 01088 && ( acct->type() == "imap" )) ) 01089 { 01090 node = the_imapFolderMgr->dir().next(); 01091 } else { 01092 the_imapFolderMgr->remove(static_cast<KMFolder*>(node)); 01093 node = the_imapFolderMgr->dir().first(); 01094 } 01095 } 01096 01097 node = the_dimapFolderMgr->dir().first(); 01098 while (node) 01099 { 01100 if (node->isDir() || ((acct = the_acctMgr->find(node->id())) 01101 && ( acct->type() == "cachedimap" )) ) 01102 { 01103 node = the_dimapFolderMgr->dir().next(); 01104 } else { 01105 the_dimapFolderMgr->remove(static_cast<KMFolder*>(node)); 01106 node = the_dimapFolderMgr->dir().first(); 01107 } 01108 } 01109 01110 the_imapFolderMgr->quiet(true); 01111 for (acct = the_acctMgr->first(); acct; acct = the_acctMgr->next()) 01112 { 01113 KMFolderImap *fld; 01114 KMAcctImap *imapAcct; 01115 01116 if (acct->type() != "imap") continue; 01117 fld = static_cast<KMFolderImap*>(the_imapFolderMgr 01118 ->findOrCreate(QString::number(acct->id()), false, acct->id())->storage()); 01119 fld->setNoContent(true); 01120 fld->folder()->setLabel(acct->name()); 01121 imapAcct = static_cast<KMAcctImap*>(acct); 01122 fld->setAccount(imapAcct); 01123 imapAcct->setImapFolder(fld); 01124 fld->close(); 01125 } 01126 the_imapFolderMgr->quiet(false); 01127 01128 the_dimapFolderMgr->quiet( true ); 01129 for (acct = the_acctMgr->first(); acct; acct = the_acctMgr->next()) 01130 { 01131 KMFolderCachedImap *cfld = 0; 01132 KMAcctCachedImap *cachedImapAcct; 01133 01134 if (acct->type() != "cachedimap" ) continue; 01135 01136 KMFolder* fld = the_dimapFolderMgr->find(QString::number(acct->id())); 01137 if( fld ) 01138 cfld = static_cast<KMFolderCachedImap*>( fld->storage() ); 01139 if (cfld == 0) { 01140 // Folder doesn't exist yet 01141 cfld = static_cast<KMFolderCachedImap*>(the_dimapFolderMgr->createFolder(QString::number(acct->id()), 01142 false, KMFolderTypeCachedImap)->storage()); 01143 if (!cfld) { 01144 KMessageBox::error(0,(i18n("Cannot create file `%1' in %2.\nKMail cannot start without it.").arg(acct->name()).arg(the_dimapFolderMgr->basePath()))); 01145 exit(-1); 01146 } 01147 } 01148 01149 cfld->setNoContent(true); 01150 cfld->folder()->setLabel(acct->name()); 01151 cachedImapAcct = static_cast<KMAcctCachedImap*>(acct); 01152 cfld->setAccount(cachedImapAcct); 01153 cachedImapAcct->setImapFolder(cfld); 01154 cfld->close(); 01155 } 01156 the_dimapFolderMgr->quiet( false ); 01157 } 01158 01159 bool KMKernel::doSessionManagement() 01160 { 01161 01162 // Do session management 01163 if (kapp->isRestored()){ 01164 int n = 1; 01165 while (KMMainWin::canBeRestored(n)){ 01166 //only restore main windows! (Matthias); 01167 if (KMMainWin::classNameOfToplevel(n) == "KMMainWin") 01168 (new KMMainWin)->restore(n); 01169 n++; 01170 } 01171 return true; // we were restored by SM 01172 } 01173 return false; // no, we were not restored 01174 } 01175 01176 void KMKernel::closeAllKMailWindows() 01177 { 01178 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 01179 KMainWindow *window = 0; 01180 while ((window = it.current()) != 0) { 01181 ++it; 01182 if (window->isA("KMMainWindow") || 01183 window->inherits("KMail::SecondaryWindow")) 01184 window->close( true ); // close and delete the window 01185 } 01186 } 01187 01188 void KMKernel::cleanup(void) 01189 { 01190 dumpDeadLetters(); 01191 mDeadLetterTimer->stop(); 01192 the_shuttingDown = true; 01193 closeAllKMailWindows(); 01194 01195 delete the_acctMgr; 01196 the_acctMgr = 0; 01197 delete the_filterMgr; 01198 the_filterMgr = 0; 01199 delete the_msgSender; 01200 the_msgSender = 0; 01201 delete the_filterActionDict; 01202 the_filterActionDict = 0; 01203 delete the_undoStack; 01204 the_undoStack = 0; 01205 delete the_popFilterMgr; 01206 the_popFilterMgr = 0; 01207 01208 #if 0 01209 delete the_weaver; 01210 the_weaver = 0; 01211 #endif 01212 01213 KConfig* config = KMKernel::config(); 01214 KConfigGroupSaver saver(config, "General"); 01215 01216 if (the_trashFolder) { 01217 01218 the_trashFolder->close(TRUE); 01219 01220 if (config->readBoolEntry("empty-trash-on-exit", true)) 01221 { 01222 if ( the_trashFolder->count( true ) > 0 ) 01223 the_trashFolder->expunge(); 01224 } 01225 } 01226 01227 mICalIface->cleanup(); 01228 01229 QValueList<QGuardedPtr<KMFolder> > folders; 01230 QStringList strList; 01231 KMFolder *folder; 01232 the_folderMgr->createFolderList(&strList, &folders); 01233 for (int i = 0; folders.at(i) != folders.end(); i++) 01234 { 01235 folder = *folders.at(i); 01236 if (!folder || folder->isDir()) continue; 01237 folder->close(TRUE); 01238 } 01239 strList.clear(); 01240 folders.clear(); 01241 the_searchFolderMgr->createFolderList(&strList, &folders); 01242 for (int i = 0; folders.at(i) != folders.end(); i++) 01243 { 01244 folder = *folders.at(i); 01245 if (!folder || folder->isDir()) continue; 01246 folder->close(TRUE); 01247 } 01248 folderMgr()->writeMsgDict(msgDict()); 01249 imapFolderMgr()->writeMsgDict(msgDict()); 01250 dimapFolderMgr()->writeMsgDict(msgDict()); 01251 delete the_msgIndex; 01252 the_msgIndex = 0; 01253 delete the_folderMgr; 01254 the_folderMgr = 0; 01255 delete the_imapFolderMgr; 01256 the_imapFolderMgr = 0; 01257 delete the_dimapFolderMgr; 01258 the_dimapFolderMgr = 0; 01259 delete the_searchFolderMgr; 01260 the_searchFolderMgr = 0; 01261 delete the_msgDict; 01262 the_msgDict = 0; 01263 delete mConfigureDialog; 01264 mConfigureDialog = 0; 01265 delete mWin; 01266 mWin = 0; 01267 01268 RecentAddresses::self( KMKernel::config() )->save( KMKernel::config() ); 01269 KMKernel::config()->sync(); 01270 } 01271 01272 //Isnīt this obsolete? (sven) 01273 void KMKernel::transferMail(void) 01274 { 01275 QDir dir = QDir::home(); 01276 int rc; 01277 01278 // Stefan: This function is for all the whiners who think that KMail is 01279 // broken because they cannot read mail with pine and do not 01280 // know how to fix this problem with a simple symbolic link =;-) 01281 // Markus: lol ;-) 01282 if (!dir.cd("KMail")) return; 01283 01284 rc = KMessageBox::questionYesNo(0, 01285 i18n( 01286 "The directory ~/KMail exists. From now on, KMail uses the " 01287 "directory ~/Mail for its messages.\n" 01288 "KMail can move the contents of the directory ~/KMail into " 01289 "~/Mail, but this will replace existing files with the same " 01290 "name in the directory ~/Mail (e.g. inbox).\n" 01291 "Should KMail move the mail folders now?")); 01292 01293 if (rc == KMessageBox::No) return; 01294 01295 dir.cd("/"); // otherwise we lock the directory 01296 //testDir("/Mail"); 01297 system("mv -f ~/KMail/* ~/Mail"); 01298 system("mv -f ~/KMail/.??* ~/Mail"); 01299 system("rmdir ~/KMail"); 01300 } 01301 01302 01303 void KMKernel::ungrabPtrKb(void) 01304 { 01305 if(!KMainWindow::memberList) return; 01306 QWidget* widg = KMainWindow::memberList->first(); 01307 Display* dpy; 01308 01309 if (!widg) return; 01310 dpy = widg->x11Display(); 01311 XUngrabKeyboard(dpy, CurrentTime); 01312 XUngrabPointer(dpy, CurrentTime); 01313 } 01314 01315 01316 // Message handler 01317 void KMKernel::kmailMsgHandler(QtMsgType aType, const char* aMsg) 01318 { 01319 static int recurse=-1; 01320 01321 recurse++; 01322 01323 switch (aType) 01324 { 01325 case QtDebugMsg: 01326 case QtWarningMsg: 01327 kdDebug(5006) << aMsg << endl; 01328 break; 01329 01330 case QtFatalMsg: // Hm, what about using kdFatal() here? 01331 ungrabPtrKb(); 01332 kdDebug(5006) << kapp->caption() << " fatal error " 01333 << aMsg << endl; 01334 KMessageBox::error(0, aMsg); 01335 abort(); 01336 } 01337 01338 recurse--; 01339 } 01340 void KMKernel::dumpDeadLetters() 01341 { 01342 if (shuttingDown()) 01343 return; //All documents should be saved before shutting down is set! 01344 mDeadLetterTimer->stop(); 01345 QWidget *win; 01346 QDir dir = QDir::home(); 01347 QString fname = dir.path(); 01348 QFile::remove(fname + "/dead.letter.tmp"); 01349 if (KMainWindow::memberList) { 01350 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 01351 01352 while ((win = it.current()) != 0) { 01353 ++it; 01354 if (::qt_cast<KMComposeWin*>(win)) ((KMComposeWin*)win)->deadLetter(); 01355 // delete win; // WABA: Don't delete, we might crash in there! 01356 } 01357 } 01358 QFile::remove(fname + "/dead.letter"); 01359 dir.rename("dead.letter.tmp","dead.letter"); 01360 if ( mDeadLetterInterval ) 01361 mDeadLetterTimer->start(mDeadLetterInterval); 01362 } 01363 01364 01365 01366 void KMKernel::action(bool mailto, bool check, const QString &to, 01367 const QString &cc, const QString &bcc, 01368 const QString &subj, const QString &body, 01369 const KURL &messageFile, 01370 const KURL::List &attachURLs) 01371 { 01372 // Run the groupware setup wizard. It doesn't do anything if this isn't 01373 // the first run. Replace this with a general wizard later 01374 // #### Disabled until we have a general startup wizard. 01375 // StartupWizard::run(); 01376 01377 if (mailto) 01378 openComposer (to, cc, bcc, subj, body, 0, messageFile, attachURLs); 01379 else 01380 openReader( check ); 01381 01382 if (check) 01383 checkMail(); 01384 //Anything else? 01385 } 01386 01387 void KMKernel::byteArrayToRemoteFile(const QByteArray &aData, const KURL &aURL, 01388 bool overwrite) 01389 { 01390 // ## when KDE 3.3 is out: use KIO::storedPut to remove slotDataReq altogether 01391 KIO::Job *job = KIO::put(aURL, -1, overwrite, FALSE); 01392 putData pd; pd.url = aURL; pd.data = aData; pd.offset = 0; 01393 mPutJobs.insert(job, pd); 01394 connect(job, SIGNAL(dataReq(KIO::Job*,QByteArray&)), 01395 SLOT(slotDataReq(KIO::Job*,QByteArray&))); 01396 connect(job, SIGNAL(result(KIO::Job*)), 01397 SLOT(slotResult(KIO::Job*))); 01398 } 01399 01400 void KMKernel::slotDataReq(KIO::Job *job, QByteArray &data) 01401 { 01402 // send the data in 64 KB chunks 01403 const int MAX_CHUNK_SIZE = 64*1024; 01404 QMap<KIO::Job*, putData>::Iterator it = mPutJobs.find(job); 01405 assert(it != mPutJobs.end()); 01406 int remainingBytes = (*it).data.size() - (*it).offset; 01407 if( remainingBytes > MAX_CHUNK_SIZE ) 01408 { 01409 // send MAX_CHUNK_SIZE bytes to the receiver (deep copy) 01410 data.duplicate( (*it).data.data() + (*it).offset, MAX_CHUNK_SIZE ); 01411 (*it).offset += MAX_CHUNK_SIZE; 01412 //kdDebug( 5006 ) << "Sending " << MAX_CHUNK_SIZE << " bytes (" 01413 // << remainingBytes - MAX_CHUNK_SIZE << " bytes remain)\n"; 01414 } 01415 else 01416 { 01417 // send the remaining bytes to the receiver (deep copy) 01418 data.duplicate( (*it).data.data() + (*it).offset, remainingBytes ); 01419 (*it).data = QByteArray(); 01420 (*it).offset = 0; 01421 //kdDebug( 5006 ) << "Sending " << remainingBytes << " bytes\n"; 01422 } 01423 } 01424 01425 void KMKernel::slotResult(KIO::Job *job) 01426 { 01427 QMap<KIO::Job*, putData>::Iterator it = mPutJobs.find(job); 01428 assert(it != mPutJobs.end()); 01429 if (job->error()) 01430 { 01431 if (job->error() == KIO::ERR_FILE_ALREADY_EXIST) 01432 { 01433 if (KMessageBox::warningContinueCancel(0, 01434 i18n("File %1 exists.\nDo you want to replace it?") 01435 .arg((*it).url.prettyURL()), i18n("Save to File"), i18n("&Replace")) 01436 == KMessageBox::Continue) 01437 byteArrayToRemoteFile((*it).data, (*it).url, TRUE); 01438 } 01439 else job->showErrorDialog(); 01440 } 01441 mPutJobs.remove(it); 01442 } 01443 01444 void KMKernel::slotRequestConfigSync() { 01445 // ### FIXME: delay as promised in the kdoc of this function ;-) 01446 KMKernel::config()->sync(); 01447 } 01448 01449 void KMKernel::slotShowConfigurationDialog() 01450 { 01451 if( !mConfigureDialog ) { 01452 mConfigureDialog = new ConfigureDialog( 0, "configure", false ); 01453 connect( mConfigureDialog, SIGNAL( configCommitted() ), 01454 this, SLOT( slotConfigChanged() ) ); 01455 } 01456 01457 if( mConfigureDialog->isHidden() ) 01458 mConfigureDialog->show(); 01459 else 01460 mConfigureDialog->raise(); 01461 } 01462 01463 void KMKernel::slotConfigChanged() 01464 { 01465 readConfig(); 01466 emit configChanged(); 01467 } 01468 01469 bool KMKernel::haveSystemTrayApplet() 01470 { 01471 return !systemTrayApplets.isEmpty(); 01472 } 01473 01474 bool KMKernel::registerSystemTrayApplet( const KSystemTray* applet ) 01475 { 01476 if ( systemTrayApplets.findIndex( applet ) == -1 ) { 01477 systemTrayApplets.append( applet ); 01478 return true; 01479 } 01480 else 01481 return false; 01482 } 01483 01484 bool KMKernel::unregisterSystemTrayApplet( const KSystemTray* applet ) 01485 { 01486 QValueList<const KSystemTray*>::iterator it = 01487 systemTrayApplets.find( applet ); 01488 if ( it != systemTrayApplets.end() ) { 01489 systemTrayApplets.remove( it ); 01490 return true; 01491 } 01492 else 01493 return false; 01494 } 01495 01496 void KMKernel::emergencyExit( const QString& reason ) 01497 { 01498 QString mesg; 01499 if ( reason.length() == 0 ) { 01500 mesg = i18n("KMail encountered a fatal error and will terminate now"); 01501 } 01502 else { 01503 mesg = i18n("KMail encountered a fatal error and will " 01504 "terminate now.\nThe error was:\n%1").arg( reason ); 01505 } 01506 01507 kdWarning() << mesg << endl; 01508 KNotifyClient::userEvent( 0, mesg, KNotifyClient::Messagebox, KNotifyClient::Error ); 01509 01510 ::exit(1); 01511 } 01512 01516 bool KMKernel::folderIsDraftOrOutbox(const KMFolder * folder) 01517 { 01518 assert( folder ); 01519 if ( folder == the_outboxFolder || folder == the_draftsFolder ) 01520 return true; 01521 01522 QString idString = folder->idString(); 01523 if ( idString.isEmpty() ) return false; 01524 01525 // search the identities if the folder matches the drafts-folder 01526 const KPIM::IdentityManager * im = identityManager(); 01527 for( KPIM::IdentityManager::ConstIterator it = im->begin(); it != im->end(); ++it ) 01528 if ( (*it).drafts() == idString ) return true; 01529 return false; 01530 } 01531 01532 bool KMKernel::folderIsTrash(KMFolder * folder) 01533 { 01534 assert(folder); 01535 if (folder == the_trashFolder) return true; 01536 QStringList actList = acctMgr()->getAccounts(false); 01537 QStringList::Iterator it( actList.begin() ); 01538 for( ; it != actList.end() ; ++it ) { 01539 KMAccount* act = acctMgr()->findByName( *it ); 01540 if ( act && ( act->trash() == folder->idString() ) ) 01541 return true; 01542 } 01543 return false; 01544 } 01545 01546 bool KMKernel::folderIsSentMailFolder( const KMFolder * folder ) 01547 { 01548 assert( folder ); 01549 if ( folder == the_sentFolder ) 01550 return true; 01551 01552 QString idString = folder->idString(); 01553 if ( idString.isEmpty() ) return false; 01554 01555 // search the identities if the folder matches the sent-folder 01556 const KPIM::IdentityManager * im = identityManager(); 01557 for( KPIM::IdentityManager::ConstIterator it = im->begin(); it != im->end(); ++it ) 01558 if ( (*it).fcc() == idString ) return true; 01559 return false; 01560 } 01561 01562 KPIM::IdentityManager * KMKernel::identityManager() { 01563 if ( !mIdentityManager ) { 01564 kdDebug(5006) << "instantating KPIM::IdentityManager" << endl; 01565 mIdentityManager = new KPIM::IdentityManager( false, this, "mIdentityManager" ); 01566 } 01567 return mIdentityManager; 01568 } 01569 01570 KMMsgDict *KMKernel::msgDict() 01571 { 01572 if (the_msgDict) 01573 return the_msgDict; 01574 the_msgDict = new KMMsgDict; 01575 folderMgr()->readMsgDict(msgDict()); 01576 imapFolderMgr()->readMsgDict(msgDict()); 01577 dimapFolderMgr()->readMsgDict(msgDict()); 01578 return the_msgDict; 01579 } 01580 01581 KMMsgIndex *KMKernel::msgIndex() 01582 { 01583 return the_msgIndex; 01584 } 01585 01586 KMainWindow* KMKernel::mainWin() 01587 { 01588 if (KMainWindow::memberList) { 01589 KMainWindow *kmWin = 0; 01590 01591 // First look for a KMMainWin. 01592 for (kmWin = KMainWindow::memberList->first(); kmWin; 01593 kmWin = KMainWindow::memberList->next()) 01594 if (kmWin->isA("KMMainWin")) 01595 return kmWin; 01596 01597 // There is no KMMainWin. Use any other KMainWindow instead (e.g. in 01598 // case we are running inside Kontact) because we anyway only need 01599 // it for modal message boxes and for KNotify events. 01600 kmWin = KMainWindow::memberList->first(); 01601 if ( kmWin ) 01602 return kmWin; 01603 } 01604 01605 // There's not a single KMainWindow. Create a KMMainWin. 01606 // This could happen if we want to pop up an error message 01607 // while we are still doing the startup wizard and no other 01608 // KMainWindow is running. 01609 mWin = new KMMainWin; 01610 return mWin; 01611 } 01612 01613 bool KMKernel::transferMailToPointMail(void) 01614 { 01615 QDir dir = QDir::home(); 01616 int rc; 01617 01618 if (!dir.cd("Mail")) return true; 01619 if( QFileInfo(QDir::homeDirPath() + QString( "/.Mail" )).exists()) 01620 { 01621 KMessageBox::information(0,QString("The directory .Mail exists. We can't move mail.")); 01622 return false; 01623 } 01624 01625 rc = KMessageBox::questionYesNo(0, 01626 i18n( 01627 "The directory ~/Mail exists. From now on, KMail uses the " 01628 "directory ~/.Mail for its messages.\n" 01629 "KMail can move the contents of the directory ~/Mail into " 01630 "~/.Mail, but this will replace existing files with the same " 01631 "name in the directory ~/.Mail (e.g. inbox).\n" 01632 "Should KMail move the mail folders now?")); 01633 01634 if (rc == KMessageBox::No) return false; 01635 01636 dir.cd("/"); // otherwise we lock the directory 01637 //testDir("/.Mail"); 01638 system("mv -f ~/Mail/ ~/.Mail"); 01639 //system("mv -f ~/Mail/.??* ~/.Mail"); 01640 system("rmdir ~/Mail"); 01641 return true; 01642 } 01643 01644 01648 void KMKernel::slotEmptyTrash() 01649 { 01650 QString title = i18n("Empty Trash"); 01651 QString text = i18n("Are you sure you want to empty the trash folders of all accounts?"); 01652 if (KMessageBox::warningContinueCancel(0, text, title, 01653 KStdGuiItem::cont(), "confirm_empty_trash") 01654 != KMessageBox::Continue) 01655 { 01656 return; 01657 } 01658 01659 for (KMAccount* acct = acctMgr()->first(); acct; acct = acctMgr()->next()) 01660 { 01661 KMFolder* trash = findFolderById(acct->trash()); 01662 if (trash) 01663 { 01664 trash->expunge(); 01665 } 01666 } 01667 } 01668 01669 KConfig* KMKernel::config() 01670 { 01671 assert(mySelf); 01672 if (!mySelf->mConfig) 01673 { 01674 mySelf->mConfig = KSharedConfig::openConfig( "kmailrc" ); 01675 // Check that all updates have been run on the config file: 01676 KMail::checkConfigUpdates(); 01677 } 01678 return mySelf->mConfig; 01679 } 01680 01681 KMGroupware & KMKernel::groupware() 01682 { 01683 assert( mGroupware ); 01684 return *mGroupware; 01685 } 01686 01687 KMailICalIfaceImpl& KMKernel::iCalIface() 01688 { 01689 assert( mICalIface ); 01690 return *mICalIface; 01691 } 01692 01693 void KMKernel::selectFolder( QString folderPath ) 01694 { 01695 kdDebug(5006)<<"Selecting a folder "<<folderPath<<endl; 01696 const QString localPrefix = i18n( "/Local" ); 01697 KMFolder *folder = kmkernel->folderMgr()->getFolderByURL( folderPath ); 01698 if ( !folder && folderPath.startsWith( localPrefix ) ) 01699 folder = the_folderMgr->getFolderByURL( folderPath.mid( localPrefix.length() ) ); 01700 if ( !folder ) 01701 folder = kmkernel->imapFolderMgr()->getFolderByURL( folderPath ); 01702 if ( !folder ) 01703 folder = kmkernel->dimapFolderMgr()->getFolderByURL( folderPath ); 01704 Q_ASSERT( folder ); 01705 01706 KMMainWidget *widget = getKMMainWidget(); 01707 Q_ASSERT( widget ); 01708 if ( !widget ) 01709 return; 01710 01711 KMFolderTree *tree = widget->folderTree(); 01712 tree->doFolderSelected( tree->indexOfFolder( folder ) ); 01713 tree->ensureItemVisible( tree->indexOfFolder( folder ) ); 01714 } 01715 01716 KMMainWidget *KMKernel::getKMMainWidget() 01717 { 01718 //This could definitely use a speadup 01719 QWidgetList *l = kapp->topLevelWidgets(); 01720 QWidgetListIt it( *l ); 01721 QWidget *wid; 01722 01723 while ( ( wid = it.current() ) != 0 ) { 01724 ++it; 01725 QObjectList *l2 = wid->topLevelWidget()->queryList( "KMMainWidget" ); 01726 if (l2 && l2->first()) { 01727 KMMainWidget* kmmw = dynamic_cast<KMMainWidget *>( l2->first() ); 01728 Q_ASSERT( kmmw ); 01729 delete l2; 01730 delete l; 01731 return kmmw; 01732 } 01733 delete l2; 01734 } 01735 delete l; 01736 return 0; 01737 } 01738 01739 void KMKernel::slotRunBackgroundTasks() // called regularly by timer 01740 { 01741 // Hidden KConfig keys. Not meant to be used, but a nice fallback in case 01742 // a stable kmail release goes out with a nasty bug in CompactionJob... 01743 KConfigGroup generalGroup( config(), "General" ); 01744 01745 if ( generalGroup.readBoolEntry( "auto-expiring", true ) ) { 01746 the_folderMgr->expireAllFolders( false /*scheduled, not immediate*/ ); 01747 the_imapFolderMgr->expireAllFolders( false /*scheduled, not immediate*/ ); 01748 the_dimapFolderMgr->expireAllFolders( false /*scheduled, not immediate*/ ); 01749 // the_searchFolderMgr: no expiry there 01750 } 01751 01752 if ( generalGroup.readBoolEntry( "auto-compaction", true ) ) { 01753 the_folderMgr->compactAllFolders( false /*scheduled, not immediate*/ ); 01754 // the_imapFolderMgr: no compaction 01755 the_dimapFolderMgr->compactAllFolders( false /*scheduled, not immediate*/ ); 01756 // the_searchFolderMgr: no compaction 01757 } 01758 01759 #ifdef DEBUG_SCHEDULER // for debugging, see jobscheduler.h 01760 mBackgroundTasksTimer->start( 60 * 1000, true ); // check again in 1 minute 01761 #else 01762 mBackgroundTasksTimer->start( 4 * 60 * 60 * 1000, true ); // check again in 4 hours 01763 #endif 01764 01765 } 01766 01767 void KMKernel::expireAllFoldersNow() // called by the GUI 01768 { 01769 the_folderMgr->expireAllFolders( true /*immediate*/ ); 01770 the_imapFolderMgr->expireAllFolders( true /*immediate*/ ); 01771 the_dimapFolderMgr->expireAllFolders( true /*immediate*/ ); 01772 } 01773 01774 void KMKernel::compactAllFolders() // called by the GUI 01775 { 01776 the_folderMgr->compactAllFolders( true /*immediate*/ ); 01777 //the_imapFolderMgr->compactAllFolders( true /*immediate*/ ); 01778 the_dimapFolderMgr->compactAllFolders( true /*immediate*/ ); 01779 } 01780 01781 KMFolder* KMKernel::findFolderById( const QString& idString ) 01782 { 01783 KMFolder * folder = the_folderMgr->findIdString( idString ); 01784 if ( !folder ) 01785 folder = the_imapFolderMgr->findIdString( idString ); 01786 if ( !folder ) 01787 folder = the_dimapFolderMgr->findIdString( idString ); 01788 if ( !folder ) 01789 folder = the_searchFolderMgr->findIdString( idString ); 01790 return folder; 01791 } 01792 01793 ::KIMProxy* KMKernel::imProxy() 01794 { 01795 return KIMProxy::instance( kapp->dcopClient() ); 01796 } 01797 01798 void KMKernel::enableMailCheck() 01799 { 01800 mMailCheckAborted = false; 01801 } 01802 01803 bool KMKernel::mailCheckAborted() const 01804 { 01805 return mMailCheckAborted; 01806 } 01807 01808 void KMKernel::abortMailCheck() 01809 { 01810 mMailCheckAborted = true; 01811 } 01812 01813 bool KMKernel::canQueryClose() 01814 { 01815 if ( KMMainWidget::mainWidgetList() && 01816 KMMainWidget::mainWidgetList()->count() > 1 ) 01817 return true; 01818 KMMainWidget *widget = getKMMainWidget(); 01819 if ( !widget ) 01820 return true; 01821 KMSystemTray* systray = widget->systray(); 01822 if ( systray && systray->mode() == GlobalSettings::EnumSystemTrayPolicy::ShowAlways ) { 01823 systray->hideKMail(); 01824 return false; 01825 } else if ( systray && systray->mode() == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) { 01826 systray->show(); 01827 systray->hideKMail(); 01828 return false; 01829 } 01830 return true; 01831 } 01832 01833 void KMKernel::messageCountChanged() 01834 { 01835 mTimeOfLastMessageCountChange = ::time( 0 ); 01836 } 01837 01838 int KMKernel::timeOfLastMessageCountChange() const 01839 { 01840 return mTimeOfLastMessageCountChange; 01841 } 01842 01843 #include "kmkernel.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 21 19:46:49 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003