kmail

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 "broadcaststatus.h"
00014 using KPIM::BroadcastStatus;
00015 #include "kmstartup.h"
00016 #include "index.h"
00017 #include "kmmainwin.h"
00018 #include "composer.h"
00019 #include "kmmsgpart.h"
00020 #include "kmreadermainwin.h"
00021 #include "kmfoldermgr.h"
00022 #include "kmfoldercachedimap.h"
00023 #include "kmacctcachedimap.h"
00024 #include "kmfiltermgr.h"
00025 #include "kmfilteraction.h"
00026 #include "kmheaders.h"
00027 #define REALLY_WANT_KMSENDER
00028 #include "kmsender.h"
00029 #undef REALLY_WANT_KMSENDER
00030 #include "undostack.h"
00031 #include "accountmanager.h"
00032 using KMail::AccountManager;
00033 #include <libtdepim/tdefileio.h>
00034 #include "kmversion.h"
00035 #include "kmreaderwin.h"
00036 #include "kmmainwidget.h"
00037 #include "kmfoldertree.h"
00038 #include "recentaddresses.h"
00039 using TDERecentAddress::RecentAddresses;
00040 #include "kmmsgdict.h"
00041 #include <libkpimidentities/identity.h>
00042 #include <libkpimidentities/identitymanager.h>
00043 #include "configuredialog.h"
00044 #include "kmcommands.h"
00045 #include "kmsystemtray.h"
00046 #include "transportmanager.h"
00047 #include "importarchivedialog.h"
00048 #include <mimelib/enum.h>
00049 
00050 #include <twin.h>
00051 #include "kmailicalifaceimpl.h"
00052 #include "mailserviceimpl.h"
00053 using KMail::MailServiceImpl;
00054 #include "mailcomposerIface.h"
00055 #include "folderIface.h"
00056 using KMail::FolderIface;
00057 #include "jobscheduler.h"
00058 #include "templateparser.h"
00059 
00060 #include <tdeapplication.h>
00061 #include <tdemessagebox.h>
00062 #include <knotifyclient.h>
00063 #include <kstaticdeleter.h>
00064 #include <kstandarddirs.h>
00065 #include <tdeconfig.h>
00066 #include <kprogress.h>
00067 #include <kpassivepopup.h>
00068 #include <dcopclient.h>
00069 #include <ksystemtray.h>
00070 #include <kpgp.h>
00071 #include <kdebug.h>
00072 #include <tdeio/netaccess.h>
00073 #include <tdewallet.h>
00074 using TDEWallet::Wallet;
00075 #include "actionscheduler.h"
00076 
00077 #include <qutf7codec.h>
00078 #include <tqvbox.h>
00079 #include <tqdir.h>
00080 #include <tqwidgetlist.h>
00081 #include <tqobjectlist.h>
00082 
00083 #include <sys/types.h>
00084 #include <dirent.h>
00085 #include <sys/stat.h>
00086 #include <unistd.h>
00087 #include <stdio.h>
00088 #include <stdlib.h>
00089 #include <assert.h>
00090 
00091 #include <X11/Xlib.h>
00092 #include <fixx11h.h>
00093 #include <tdecmdlineargs.h>
00094 #include <tdestartupinfo.h>
00095 
00096 KMKernel *KMKernel::mySelf = 0;
00097 static bool s_askingToGoOnline = false;
00098 
00099 /********************************************************************/
00100 /*                     Constructor and destructor                   */
00101 /********************************************************************/
00102 KMKernel::KMKernel (TQObject *parent, const char *name) :
00103   DCOPObject("KMailIface"), TQObject(parent, name),
00104   mIdentityManager(0), mConfigureDialog(0),
00105   mContextMenuShown( false ), mWallet( 0 )
00106 {
00107   kdDebug(5006) << "KMKernel::KMKernel" << endl;
00108   mySelf = this;
00109   the_startingUp = true;
00110   closed_by_user = true;
00111   the_firstInstance = true;
00112   the_msgIndex = 0;
00113 
00114   the_inboxFolder = 0;
00115   the_outboxFolder = 0;
00116   the_sentFolder = 0;
00117   the_trashFolder = 0;
00118   the_draftsFolder = 0;
00119   the_templatesFolder = 0;
00120 
00121   the_folderMgr = 0;
00122   the_imapFolderMgr = 0;
00123   the_dimapFolderMgr = 0;
00124   the_searchFolderMgr = 0;
00125   the_undoStack = 0;
00126   the_acctMgr = 0;
00127   the_filterMgr = 0;
00128   the_popFilterMgr = 0;
00129   the_filterActionDict = 0;
00130   the_msgSender = 0;
00131   mWin = 0;
00132   mMailCheckAborted = false;
00133 
00134   // make sure that we check for config updates before doing anything else
00135   KMKernel::config();
00136   // this shares the kmailrc parsing too (via TDESharedConfig), and reads values from it
00137   // so better do it here, than in some code where changing the group of config()
00138   // would be unexpected
00139   GlobalSettings::self();
00140 
00141   // Set up DCOP interface
00142   mICalIface = new KMailICalIfaceImpl();
00143 
00144   mJobScheduler = new JobScheduler( this );
00145 
00146   mXmlGuiInstance = 0;
00147 
00148   new Kpgp::Module();
00149 
00150   // register our own (libtdenetwork) utf-7 codec as long as TQt
00151   // doesn't have it's own:
00152   if ( !TQTextCodec::codecForName("utf-7") ) {
00153     kdDebug(5006) << "No TQt-native utf-7 codec found; registering TQUtf7Codec from libtdenetwork" << endl;
00154     (void) new TQUtf7Codec();
00155   }
00156 
00157   // In the case of Japan. Japanese locale name is "eucjp" but
00158   // The Japanese mail systems normally used "iso-2022-jp" of locale name.
00159   // We want to change locale name from eucjp to iso-2022-jp at KMail only.
00160   if ( TQCString(TQTextCodec::codecForLocale()->name()).lower() == "eucjp" )
00161   {
00162     netCodec = TQTextCodec::codecForName("jis7");
00163     // TQTextCodec *cdc = TQTextCodec::codecForName("jis7");
00164     // TQTextCodec::setCodecForLocale(cdc);
00165     // TDEGlobal::locale()->setEncoding(cdc->mibEnum());
00166   } else {
00167     netCodec = TQTextCodec::codecForLocale();
00168   }
00169   mMailService =  new MailServiceImpl();
00170 
00171   connectDCOPSignal( 0, 0, "kmailSelectFolder(TQString)",
00172                      "selectFolder(TQString)", false );
00173 
00174 #ifdef __TDE_HAVE_TDEHWLIB
00175   mNetworkManager = TDEGlobal::networkManager();
00176   if (mNetworkManager) {
00177     connect( mNetworkManager, TQT_SIGNAL( networkDeviceStateChanged( TDENetworkConnectionStatus::TDENetworkConnectionStatus, TDENetworkConnectionStatus::TDENetworkConnectionStatus, TQString ) ),
00178         this, TQT_SLOT( slotNetworkStateChanged( TDENetworkConnectionStatus::TDENetworkConnectionStatus, TDENetworkConnectionStatus::TDENetworkConnectionStatus, TQString ) ) );
00179     if (networkStateConnected()) {
00180       resumeNetworkJobs();
00181     }
00182     else {
00183       stopNetworkJobs();
00184     }
00185   }
00186 #endif
00187 }
00188 
00189 KMKernel::~KMKernel ()
00190 {
00191   TQMap<TDEIO::Job*, putData>::Iterator it = mPutJobs.begin();
00192   while ( it != mPutJobs.end() )
00193   {
00194     TDEIO::Job *job = it.key();
00195     mPutJobs.remove( it );
00196     job->kill();
00197     it = mPutJobs.begin();
00198   }
00199 
00200   delete mICalIface;
00201   mICalIface = 0;
00202   delete mMailService;
00203   mMailService = 0;
00204 
00205   GlobalSettings::self()->writeConfig();
00206   delete mWallet;
00207   mWallet = 0;
00208   mySelf = 0;
00209   kdDebug(5006) << "KMKernel::~KMKernel" << endl;
00210 }
00211 
00212 bool KMKernel::handleCommandLine( bool noArgsOpensReader )
00213 {
00214   TQString to, cc, bcc, subj, body;
00215   QCStringList customHeaders;
00216   KURL messageFile;
00217   KURL::List attachURLs;
00218   bool mailto = false;
00219   bool checkMail = false;
00220   bool viewOnly = false;
00221   bool calledWithSession = false; // for ignoring '-session foo'
00222 
00223   // process args:
00224   TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
00225   if (!args->getOption("subject").isNull())
00226   {
00227      subj = TQString::fromLocal8Bit(args->getOption("subject"));
00228      // if kmail is called with 'kmail -session abc' then this doesn't mean
00229      // that the user wants to send a message with subject "ession" but
00230      // (most likely) that the user clicked on KMail's system tray applet
00231      // which results in KMKernel::raise() calling "kmail kmail newInstance"
00232      // via dcop which apparently executes the application with the original
00233      // command line arguments and those include "-session ..." if
00234      // kmail/kontact was restored by session management
00235      if ( subj == "ession" ) {
00236        subj = TQString();
00237        calledWithSession = true;
00238      }
00239      else
00240        mailto = true;
00241   }
00242 
00243   if (!args->getOption("cc").isNull())
00244   {
00245      mailto = true;
00246      cc = TQString::fromLocal8Bit(args->getOption("cc"));
00247   }
00248 
00249   if (!args->getOption("bcc").isNull())
00250   {
00251      mailto = true;
00252      bcc = TQString::fromLocal8Bit(args->getOption("bcc"));
00253   }
00254 
00255   if (!args->getOption("msg").isNull())
00256   {
00257      mailto = true;
00258      messageFile.setPath( TQString::fromLocal8Bit(args->getOption("msg")) );
00259   }
00260 
00261   if (!args->getOption("body").isNull())
00262   {
00263      mailto = true;
00264      body = TQString::fromLocal8Bit(args->getOption("body"));
00265   }
00266 
00267   QCStringList attachList = args->getOptionList("attach");
00268   if (!attachList.isEmpty())
00269   {
00270      mailto = true;
00271      for ( QCStringList::Iterator it = attachList.begin() ; it != attachList.end() ; ++it )
00272        if ( !(*it).isEmpty() )
00273          attachURLs += KURL( TQString::fromLocal8Bit( *it ) );
00274   }
00275 
00276   customHeaders = args->getOptionList("header");
00277 
00278   if (args->isSet("composer"))
00279     mailto = true;
00280 
00281   if (args->isSet("check"))
00282     checkMail = true;
00283 
00284   if ( !args->getOption( "view" ).isNull() ) {
00285     viewOnly = true;
00286     const TQString filename =
00287       TQString::fromLocal8Bit( args->getOption( "view" ) );
00288     messageFile = KURL::fromPathOrURL( filename );
00289     if ( !messageFile.isValid() ) {
00290       messageFile = KURL();
00291       messageFile.setPath( filename );
00292     }
00293   }
00294 
00295   if ( !calledWithSession ) {
00296     // only read additional command line arguments if kmail/kontact is
00297     // not called with "-session foo"
00298     for(int i= 0; i < args->count(); i++)
00299     {
00300       if (strncasecmp(args->arg(i),"mailto:",7)==0)
00301         to += args->url(i).path() + ", ";
00302       else {
00303         TQString tmpArg = TQString::fromLocal8Bit( args->arg(i) );
00304         KURL url( tmpArg );
00305         if ( url.isValid() )
00306           attachURLs += url;
00307         else
00308           to += tmpArg + ", ";
00309       }
00310       mailto = true;
00311     }
00312     if ( !to.isEmpty() ) {
00313       // cut off the superfluous trailing ", "
00314       to.truncate( to.length() - 2 );
00315     }
00316   }
00317 
00318   if ( !calledWithSession )
00319     args->clear();
00320 
00321   if ( !noArgsOpensReader && !mailto && !checkMail && !viewOnly )
00322     return false;
00323 
00324   if ( viewOnly )
00325     viewMessage( messageFile );
00326   else
00327     action( mailto, checkMail, to, cc, bcc, subj, body, messageFile,
00328             attachURLs, customHeaders );
00329   return true;
00330 }
00331 
00332 /********************************************************************/
00333 /*             DCOP-callable, and command line actions              */
00334 /********************************************************************/
00335 void KMKernel::checkMail () //might create a new reader but won't show!!
00336 {
00337   if ( !kmkernel->askToGoOnline() )
00338     return;
00339   kmkernel->acctMgr()->checkMail(false);
00340 }
00341 
00342 TQStringList KMKernel::accounts()
00343 {
00344   if( kmkernel->acctMgr() )
00345      return kmkernel->acctMgr()->getAccounts();
00346   return TQStringList();
00347 }
00348 
00349 void KMKernel::checkAccount (const TQString &account) //might create a new reader but won't show!!
00350 {
00351   kdDebug(5006) << "KMKernel::checkMail called" << endl;
00352 
00353   KMAccount* acct = kmkernel->acctMgr()->findByName(account);
00354   if (acct)
00355     kmkernel->acctMgr()->singleCheckMail(acct, false);
00356 }
00357 
00358 void KMKernel::loadProfile( const TQString& )
00359 {
00360 }
00361 
00362 void KMKernel::saveToProfile( const TQString& ) const
00363 {
00364 }
00365 
00366 void KMKernel::openReader( bool onlyCheck )
00367 {
00368   mWin = 0;
00369   TDEMainWindow *ktmw = 0;
00370   kdDebug(5006) << "KMKernel::openReader called" << endl;
00371 
00372   if (TDEMainWindow::memberList)
00373     for (ktmw = TDEMainWindow::memberList->first(); ktmw;
00374          ktmw = TDEMainWindow::memberList->next())
00375       if (ktmw->isA("KMMainWin"))
00376         break;
00377 
00378   bool activate;
00379   if (ktmw) {
00380     mWin = (KMMainWin *) ktmw;
00381     activate = !onlyCheck; // existing window: only activate if not --check
00382     if ( activate )
00383        mWin->show();
00384   } else {
00385     mWin = new KMMainWin;
00386     mWin->show();
00387     activate = false; // new window: no explicit activation (#73591)
00388   }
00389 
00390   if ( activate ) {
00391     // Activate window - doing this instead of KWin::activateWindow(mWin->winId());
00392     // so that it also works when called from KMailApplication::newInstance()
00393 #if defined TQ_WS_X11 && ! defined K_WS_TQTONLY
00394     TDEStartupInfo::setNewStartupId( mWin, kapp->startupId() );
00395 #endif
00396   }
00397 }
00398 
00399 int KMKernel::openComposer (const TQString &to, const TQString &cc,
00400                             const TQString &bcc, const TQString &subject,
00401                             const TQString &body, int hidden,
00402                             const KURL &messageFile,
00403                             const KURL::List &attachURLs,
00404                             const QCStringList &customHeaders)
00405 {
00406   kdDebug(5006) << "KMKernel::openComposer called" << endl;
00407   KMMessage *msg = new KMMessage;
00408   msg->initHeader();
00409   msg->setCharset("utf-8");
00410   // tentatively decode to, cc and bcc because invokeMailer calls us with
00411   // RFC 2047 encoded addresses in order to protect non-ASCII email addresses
00412   if (!to.isEmpty())
00413     msg->setTo( KMMsgBase::decodeRFC2047String( to.latin1() ) );
00414   if (!cc.isEmpty())
00415     msg->setCc( KMMsgBase::decodeRFC2047String( cc.latin1() ) );
00416   if (!bcc.isEmpty())
00417     msg->setBcc( KMMsgBase::decodeRFC2047String( bcc.latin1() ) );
00418   if (!subject.isEmpty()) msg->setSubject(subject);
00419   if (!messageFile.isEmpty() && messageFile.isLocalFile()) {
00420     TQCString str = KPIM::kFileToString( messageFile.path(), true, false );
00421     if( !str.isEmpty() ) {
00422       msg->setBody( TQString(TQString::fromLocal8Bit( str )).utf8() );
00423     } else {
00424       TemplateParser parser( msg, TemplateParser::NewMessage );
00425       parser.process( NULL, NULL );
00426     }
00427   }
00428   else if (!body.isEmpty())
00429   {
00430     msg->setBody(body.utf8());
00431   }
00432   else
00433   {
00434     TemplateParser parser( msg, TemplateParser::NewMessage );
00435     parser.process( NULL, NULL );
00436   }
00437 
00438   if (!customHeaders.isEmpty())
00439   {
00440     for ( QCStringList::ConstIterator it = customHeaders.begin() ; it != customHeaders.end() ; ++it )
00441       if ( !(*it).isEmpty() )
00442       {
00443         const int pos = (*it).find( ':' );
00444         if ( pos > 0 )
00445         {
00446           TQCString header, value;
00447           header = (*it).left( pos ).stripWhiteSpace();
00448           value = (*it).mid( pos+1 ).stripWhiteSpace();
00449           if ( !header.isEmpty() && !value.isEmpty() )
00450             msg->setHeaderField( header, value );
00451         }
00452       }
00453   }
00454 
00455   KMail::Composer * cWin = KMail::makeComposer( msg );
00456   cWin->setCharset("", true);
00457   for ( KURL::List::ConstIterator it = attachURLs.begin() ; it != attachURLs.end() ; ++it )
00458     cWin->addAttach((*it));
00459   if (hidden == 0) {
00460     cWin->show();
00461     // Activate window - doing this instead of KWin::activateWindow(cWin->winId());
00462     // so that it also works when called from KMailApplication::newInstance()
00463 #if defined TQ_WS_X11 && ! defined K_WS_TQTONLY
00464     TDEStartupInfo::setNewStartupId( cWin, kapp->startupId() );
00465 #endif
00466   }
00467   return 1;
00468 }
00469 
00470 
00471 int KMKernel::openComposer (const TQString &to, const TQString &cc,
00472                             const TQString &bcc, const TQString &subject,
00473                             const TQString &body, int hidden,
00474                             const TQString &attachName,
00475                             const TQCString &attachCte,
00476                             const TQCString &attachData,
00477                             const TQCString &attachType,
00478                             const TQCString &attachSubType,
00479                             const TQCString &attachParamAttr,
00480                             const TQString &attachParamValue,
00481                             const TQCString &attachContDisp )
00482 {
00483   kdDebug(5006) << "KMKernel::openComposer called (deprecated version)" << endl;
00484 
00485   return openComposer ( to, cc, bcc, subject, body, hidden,
00486                         attachName, attachCte, attachData,
00487                         attachType, attachSubType, attachParamAttr,
00488                         attachParamValue, attachContDisp, TQCString() );
00489 }
00490 
00491 int KMKernel::openComposer (const TQString &to, const TQString &cc,
00492                             const TQString &bcc, const TQString &subject,
00493                             const TQString &body, int hidden,
00494                             const TQString &attachName,
00495                             const TQCString &attachCte,
00496                             const TQCString &attachData,
00497                             const TQCString &attachType,
00498                             const TQCString &attachSubType,
00499                             const TQCString &attachParamAttr,
00500                             const TQString &attachParamValue,
00501                             const TQCString &attachContDisp,
00502                             const TQCString &attachCharset )
00503 {
00504   kdDebug(5006) << "KMKernel::openComposer called (deprecated version)" << endl;
00505   return openComposer ( to, cc, bcc, subject, body, hidden,
00506                         attachName, attachCte, attachData,
00507                         attachType, attachSubType, attachParamAttr,
00508                         attachParamValue, attachContDisp, attachCharset, 0 );
00509 }
00510 
00511 int KMKernel::openComposer (const TQString &to, const TQString &cc,
00512                             const TQString &bcc, const TQString &subject,
00513                             const TQString &body, int hidden,
00514                             const TQString &attachName,
00515                             const TQCString &attachCte,
00516                             const TQCString &attachData,
00517                             const TQCString &attachType,
00518                             const TQCString &attachSubType,
00519                             const TQCString &attachParamAttr,
00520                             const TQString &attachParamValue,
00521                             const TQCString &attachContDisp,
00522                             const TQCString &attachCharset,
00523                             unsigned int identity )
00524 {
00525   kdDebug(5006) << "KMKernel::openComposer()" << endl;
00526 
00527   KMMessage *msg = new KMMessage;
00528   KMMessagePart *msgPart = 0;
00529   msg->initHeader();
00530   msg->setCharset( "utf-8" );
00531   if ( !cc.isEmpty() ) msg->setCc(cc);
00532   if ( !bcc.isEmpty() ) msg->setBcc(bcc);
00533   if ( !subject.isEmpty() ) msg->setSubject(subject);
00534   if ( !to.isEmpty() ) msg->setTo(to);
00535   if ( identity > 0 ) msg->setHeaderField( "X-KMail-Identity", TQString::number( identity ) );
00536   if ( !body.isEmpty() ) {
00537     msg->setBody(body.utf8());
00538   } else {
00539     TemplateParser parser( msg, TemplateParser::NewMessage );
00540     parser.process( NULL, NULL );
00541   }
00542 
00543   bool iCalAutoSend = false;
00544   bool noWordWrap = false;
00545   bool isICalInvitation = false;
00546   TDEConfigGroup options( config(), "Groupware" );
00547   if ( !attachData.isEmpty() ) {
00548     isICalInvitation = attachName == "cal.ics" &&
00549       attachType == "text" &&
00550       attachSubType == "calendar" &&
00551       attachParamAttr == "method";
00552     // Remove BCC from identity on ical invitations (https://intevation.de/roundup/kolab/issue474)
00553     if ( isICalInvitation && bcc.isEmpty() )
00554       msg->setBcc( "" );
00555     if ( isICalInvitation &&
00556         GlobalSettings::self()->legacyBodyInvites() ) {
00557       // KOrganizer invitation caught and to be sent as body instead
00558       msg->setBody( attachData );
00559       msg->setHeaderField( "Content-Type",
00560                            TQString( "text/calendar; method=%1; "
00561                                     "charset=\"utf-8\"" ).
00562                            arg( attachParamValue ) );
00563 
00564       iCalAutoSend = true; // no point in editing raw ICAL
00565       noWordWrap = true; // we shant word wrap inline invitations
00566     } else {
00567       // Just do what we're told to do
00568       msgPart = new KMMessagePart;
00569       msgPart->setName( attachName );
00570       msgPart->setCteStr( attachCte );
00571       msgPart->setBodyEncoded( attachData );
00572       msgPart->setTypeStr( attachType );
00573       msgPart->setSubtypeStr( attachSubType );
00574       msgPart->setParameter( attachParamAttr, attachParamValue );
00575        if( ! GlobalSettings::self()->exchangeCompatibleInvitations() ) {
00576         msgPart->setContentDisposition( attachContDisp );
00577       }
00578       if( !attachCharset.isEmpty() && (msgPart->type() == DwMime::kTypeText) ) {
00579         // kdDebug(5006) << "KMKernel::openComposer set attachCharset to "
00580         // << attachCharset << endl;
00581         msgPart->setCharset( attachCharset );
00582       }
00583       // Don't show the composer window, if the automatic sending is checked
00584       TDEConfigGroup options( config(), "Groupware" );
00585       iCalAutoSend = options.readBoolEntry( "AutomaticSending", true );
00586     }
00587   }
00588 
00589   KMail::Composer * cWin = KMail::makeComposer();
00590   cWin->setMsg( msg, !isICalInvitation /* mayAutoSign */ );
00591   cWin->setSigningAndEncryptionDisabled( isICalInvitation
00592       && GlobalSettings::self()->legacyBodyInvites() );
00593   cWin->setAutoDelete( true );
00594   if( noWordWrap )
00595     cWin->disableWordWrap();
00596   else
00597     cWin->setCharset( "", true );
00598   if ( msgPart )
00599     cWin->addAttach(msgPart);
00600 
00601   if ( isICalInvitation ) {
00602     cWin->disableRecipientNumberCheck();
00603     cWin->disableForgottenAttachmentsCheck();
00604   }
00605 
00606   if ( hidden == 0 && !iCalAutoSend ) {
00607     cWin->show();
00608     // Activate window - doing this instead of KWin::activateWindow(cWin->winId());
00609     // so that it also works when called from KMailApplication::newInstance()
00610 #if defined TQ_WS_X11 && ! defined K_WS_TQTONLY
00611     TDEStartupInfo::setNewStartupId( cWin, kapp->startupId() );
00612 #endif
00613   } else {
00614     cWin->setAutoDeleteWindow( true );
00615     cWin->slotSendNow();
00616   }
00617 
00618   return 1;
00619 }
00620 
00621 void KMKernel::setDefaultTransport( const TQString & transport )
00622 {
00623   TQStringList availTransports = KMail::TransportManager::transportNames();
00624   TQStringList::const_iterator it = availTransports.find( transport );
00625   if ( it == availTransports.end() ) {
00626     kdWarning() << "The transport you entered is not available" << endl;
00627     return;
00628   }
00629   GlobalSettings::self()->setDefaultTransport( transport );
00630 }
00631 
00632 DCOPRef KMKernel::openComposer(const TQString &to, const TQString &cc,
00633                                const TQString &bcc, const TQString &subject,
00634                                const TQString &body,bool hidden)
00635 {
00636   KMMessage *msg = new KMMessage;
00637   msg->initHeader();
00638   msg->setCharset("utf-8");
00639   if (!cc.isEmpty()) msg->setCc(cc);
00640   if (!bcc.isEmpty()) msg->setBcc(bcc);
00641   if (!subject.isEmpty()) msg->setSubject(subject);
00642   if (!to.isEmpty()) msg->setTo(to);
00643   if (!body.isEmpty()) {
00644     msg->setBody(body.utf8());
00645   } else {
00646     TemplateParser parser( msg, TemplateParser::NewMessage );
00647     parser.process( NULL, NULL );
00648   }
00649 
00650   KMail::Composer * cWin = KMail::makeComposer( msg );
00651   cWin->setCharset("", true);
00652   if (!hidden) {
00653     cWin->show();
00654     // Activate window - doing this instead of KWin::activateWindow(cWin->winId());
00655     // so that it also works when called from KMailApplication::newInstance()
00656 #if defined TQ_WS_X11 && ! defined K_WS_TQTONLY
00657     TDEStartupInfo::setNewStartupId( cWin, kapp->startupId() );
00658 #endif
00659   }
00660 
00661   return DCOPRef( cWin->asMailComposerIFace() );
00662 }
00663 
00664 DCOPRef KMKernel::newMessage(const TQString &to,
00665                              const TQString &cc,
00666                              const TQString &bcc,
00667                              bool hidden,
00668                              bool useFolderId,
00669                              const KURL & /*messageFile*/,
00670                              const KURL &attachURL)
00671 {
00672   KMail::Composer * win = 0;
00673   KMMessage *msg = new KMMessage;
00674   KMFolder *folder = NULL;
00675   uint id;
00676 
00677   if ( useFolderId ) {
00678     //create message with required folder identity
00679     folder = currentFolder();
00680     id = folder ? folder->identity() : 0;
00681     msg->initHeader( id );
00682   } else {
00683     msg->initHeader();
00684   }
00685   msg->setCharset("utf-8");
00686   //set basic headers
00687   if (!to.isEmpty()) msg->setTo(to);
00688   if (!cc.isEmpty()) msg->setCc(cc);
00689   if (!bcc.isEmpty()) msg->setBcc(bcc);
00690 
00691   if ( useFolderId ) {
00692     TemplateParser parser( msg, TemplateParser::NewMessage );
00693     parser.process( NULL, folder );
00694     win = makeComposer( msg, id );
00695   } else {
00696     TemplateParser parser( msg, TemplateParser::NewMessage );
00697     parser.process( NULL, folder );
00698     win = makeComposer( msg );
00699   }
00700 
00701   //Add the attachment if we have one
00702   if(!attachURL.isEmpty() && attachURL.isValid()) {
00703     win->addAttach(attachURL);
00704   }
00705 
00706   //only show window when required
00707   if(!hidden) {
00708     win->show();
00709   }
00710   return DCOPRef( win->asMailComposerIFace() );
00711 }
00712 
00713 int KMKernel::viewMessage( const KURL & messageFile )
00714 {
00715   KMOpenMsgCommand *openCommand = new KMOpenMsgCommand( 0, messageFile );
00716 
00717   openCommand->start();
00718 
00719   return 1;
00720 }
00721 
00722 int KMKernel::sendCertificate( const TQString& to, const TQByteArray& certData )
00723 {
00724   KMMessage *msg = new KMMessage;
00725   msg->initHeader();
00726   msg->setCharset("utf-8");
00727   msg->setSubject( i18n( "Certificate Signature Request" ) );
00728   if (!to.isEmpty()) msg->setTo(to);
00729   // ### Make this message customizable via KIOSK
00730   msg->setBody( i18n( "Please create a certificate from attachment and return to sender." ).utf8() );
00731 
00732   KMail::Composer * cWin = KMail::makeComposer( msg );
00733   cWin->setCharset("", true);
00734   cWin->slotSetAlwaysSend( true );
00735   if (!certData.isEmpty()) {
00736     KMMessagePart *msgPart = new KMMessagePart;
00737     msgPart->setName("smime.p10");
00738     msgPart->setCteStr("base64");
00739     msgPart->setBodyEncodedBinary(certData);
00740     msgPart->setTypeStr("application");
00741     msgPart->setSubtypeStr("pkcs10");
00742     msgPart->setContentDisposition("attachment; filename=smime.p10");
00743     cWin->addAttach(msgPart);
00744   }
00745 
00746   cWin->show();
00747   return 1;
00748 }
00749 
00750 KMMsgStatus KMKernel::strToStatus(const TQString &flags)
00751 {
00752     KMMsgStatus status = 0;
00753     if (!flags.isEmpty()) {
00754         for (uint n = 0; n < flags.length() ; n++) {
00755             switch (flags[n]) {
00756                 case 'N':
00757                     status |= KMMsgStatusNew;
00758                     break;
00759                 case 'U':
00760                     status |= KMMsgStatusUnread;
00761                     break;
00762                 case 'O':
00763                     status |= KMMsgStatusOld;
00764                     break;
00765                 case 'R':
00766                     status |= KMMsgStatusRead;
00767                     break;
00768                 case 'D':
00769                     status |= KMMsgStatusDeleted;
00770                     break;
00771                 case 'A':
00772                     status |= KMMsgStatusReplied;
00773                     break;
00774                 case 'F':
00775                     status |= KMMsgStatusForwarded;
00776                     break;
00777                 case 'Q':
00778                     status |= KMMsgStatusQueued;
00779                     break;
00780                 case 'K':
00781                     status |= KMMsgStatusTodo;
00782                     break;
00783                 case 'S':
00784                     status |= KMMsgStatusSent;
00785                     break;
00786                 case 'G':
00787                     status |= KMMsgStatusFlag;
00788                     break;
00789                 case 'W':
00790                     status |= KMMsgStatusWatched;
00791                     break;
00792                 case 'I':
00793                     status |= KMMsgStatusIgnored;
00794                     break;
00795                 case 'P':
00796                     status |= KMMsgStatusSpam;
00797                     break;
00798                 case 'H':
00799                     status |= KMMsgStatusHam;
00800                     break;
00801                 case 'T':
00802                     status |= KMMsgStatusHasAttach;
00803                     break;
00804                 case 'C':
00805                     status |= KMMsgStatusHasNoAttach;
00806                     break;
00807                 default:
00808                     break;
00809             }
00810         }
00811     }
00812     return status;
00813 }
00814 
00815 int KMKernel::dcopAddMessage( const TQString & foldername, const TQString & msgUrlString,
00816                               const TQString & MsgStatusFlags)
00817 {
00818   return dcopAddMessage(foldername, KURL(msgUrlString), MsgStatusFlags);
00819 }
00820 
00821 int KMKernel::dcopAddMessage( const TQString & foldername,const KURL & msgUrl,
00822                               const TQString & MsgStatusFlags)
00823 {
00824   kdDebug(5006) << "KMKernel::dcopAddMessage called" << endl;
00825 
00826   if ( foldername.isEmpty() || foldername.startsWith("."))
00827     return -1;
00828 
00829   int retval;
00830   bool readFolderMsgIds = false;
00831   TQString _foldername = foldername.stripWhiteSpace();
00832   _foldername = _foldername.replace('\\',""); //try to prevent ESCAPE Sequences
00833 
00834   if ( foldername != mAddMessageLastFolder ) {
00835     mAddMessageMsgIds.clear();
00836     readFolderMsgIds = true;
00837     mAddMessageLastFolder = foldername;
00838   }
00839 
00840   if (!msgUrl.isEmpty() && msgUrl.isLocalFile()) {
00841 
00842     // This is a proposed change by Daniel Andor.
00843     // He proposed to change from the fopen(blah)
00844     // to a KPIM::kFileToString(blah).
00845     // Although it assigns a TQString to a TQString,
00846     // because of the implicit sharing this poses
00847     // no memory or performance penalty.
00848 
00849     const TQCString messageText =
00850       KPIM::kFileToString( msgUrl.path(), true, false );
00851     if ( messageText.isEmpty() )
00852       return -2;
00853 
00854     KMMessage *msg = new KMMessage();
00855     msg->fromString( messageText );
00856 
00857     if (readFolderMsgIds) {
00858       if ( foldername.contains("/")) {
00859         TQString tmp_fname = "";
00860         KMFolder *folder = NULL;
00861         KMFolderDir *subfolder;
00862         bool root = true;
00863 
00864         TQStringList subFList = TQStringList::split("/",_foldername,false);
00865 
00866         for ( TQStringList::Iterator it = subFList.begin(); it != subFList.end(); ++it ) {
00867           TQString _newFolder = *it;
00868           if(_newFolder.startsWith(".")) return -1;
00869 
00870           if(root) {
00871             folder = the_folderMgr->findOrCreate(*it, false);
00872             if (folder) {
00873               root = false;
00874               tmp_fname = "/" + *it;
00875             }
00876             else return -1;
00877           } else {
00878             subfolder = folder->createChildFolder();
00879             tmp_fname += "/" + *it;
00880             if(!the_folderMgr->getFolderByURL( tmp_fname )) {
00881              folder = the_folderMgr->createFolder(*it, false, folder->folderType(), subfolder);
00882             }
00883 
00884             if(!(folder = the_folderMgr->getFolderByURL( tmp_fname ))) return -1;
00885           }
00886         }
00887 
00888         mAddMsgCurrentFolder = the_folderMgr->getFolderByURL( tmp_fname );
00889         if(!folder) return -1;
00890 
00891       } else {
00892         mAddMsgCurrentFolder = the_folderMgr->findOrCreate(_foldername, false);
00893       }
00894     }
00895 
00896     if ( mAddMsgCurrentFolder ) {
00897       if (readFolderMsgIds) {
00898 
00899         // OLD COMMENT:
00900         // Try to determine if a message already exists in
00901         // the folder. The message id that is searched for, is
00902         // the subject line + the date. This should be quite
00903         // unique. The change that a given date with a given
00904         // subject is in the folder twice is very small.
00905         // If the subject is empty, the fromStrip string
00906         // is taken.
00907 
00908     // NEW COMMENT from Danny Kukawka (danny.kukawka@web.de):
00909     // subject line + the date is only unique if the following
00910     // return a correct unique value:
00911     //  time_t  DT = mb->date();
00912         //  TQString dt = ctime(&DT);
00913     // But if the datestring in the Header isn't RFC conform
00914     // subject line + the date isn't unique.
00915     //
00916     // The only uique headerfield is the Message-ID. In some
00917     // cases this could be empty. I then I use the
00918     // subject line + dateStr .
00919 
00920         int i;
00921 
00922         mAddMsgCurrentFolder->open("dcopadd");
00923         for( i=0; i<mAddMsgCurrentFolder->count(); i++) {
00924           KMMsgBase *mb = mAddMsgCurrentFolder->getMsgBase(i);
00925       TQString id = mb->msgIdMD5();
00926       if ( id.isEmpty() ) {
00927             id = mb->subject();
00928             if ( id.isEmpty() )
00929               id = mb->fromStrip();
00930             if ( id.isEmpty() )
00931               id = mb->toStrip();
00932 
00933             id += mb->dateStr();
00934       }
00935 
00936           //fprintf(stderr,"%s\n",(const char *) id);
00937           if ( !id.isEmpty() ) {
00938             mAddMessageMsgIds.append(id);
00939           }
00940         }
00941         mAddMsgCurrentFolder->close("dcopadd");
00942       }
00943 
00944       TQString msgId = msg->msgIdMD5();
00945       if ( msgId.isEmpty()) {
00946     msgId = msg->subject();
00947     if ( msgId.isEmpty() )
00948           msgId = msg->fromStrip();
00949         if ( msgId.isEmpty() )
00950           msgId = msg->toStrip();
00951 
00952     msgId += msg->dateStr();
00953       }
00954 
00955       int k = mAddMessageMsgIds.findIndex( msgId );
00956       //fprintf(stderr,"find %s = %d\n",(const char *) msgId,k);
00957 
00958       if ( k == -1 ) {
00959         if ( !msgId.isEmpty() ) {
00960           mAddMessageMsgIds.append( msgId );
00961         }
00962 
00963         if ( !MsgStatusFlags.isEmpty() ) {
00964           KMMsgStatus status = strToStatus(MsgStatusFlags);
00965           if (status) msg->setStatus(status);
00966         }
00967 
00968         int index;
00969         if ( mAddMsgCurrentFolder->addMsg( msg, &index ) == 0 ) {
00970           mAddMsgCurrentFolder->unGetMsg( index );
00971           retval = 1;
00972         } else {
00973           retval =- 2;
00974           delete msg;
00975           msg = 0;
00976         }
00977       } else {
00978         //tqDebug( "duplicate: " + msgId + "; subj: " + msg->subject() + ", from: " + msgId = msg->fromStrip());
00979     retval = -4;
00980       }
00981     } else {
00982       retval = -1;
00983     }
00984   } else {
00985     retval = -2;
00986   }
00987   return retval;
00988 }
00989 
00990 void KMKernel::dcopResetAddMessage()
00991 {
00992   mAddMessageMsgIds.clear();
00993   mAddMessageLastFolder = TQString();
00994 }
00995 
00996 int KMKernel::dcopAddMessage_fastImport( const TQString & foldername,
00997                                          const TQString & msgUrlString,
00998                                          const TQString & MsgStatusFlags)
00999 {
01000   return dcopAddMessage_fastImport(foldername, KURL(msgUrlString), MsgStatusFlags);
01001 }
01002 
01003 int KMKernel::dcopAddMessage_fastImport( const TQString & foldername,
01004                                          const KURL & msgUrl,
01005                                          const TQString & MsgStatusFlags)
01006 {
01007   // Use this function to import messages without
01008   // search for already existing emails.
01009   kdDebug(5006) << "KMKernel::dcopAddMessage_fastImport called" << endl;
01010 
01011   if ( foldername.isEmpty() || foldername.startsWith("."))
01012     return -1;
01013 
01014   int retval;
01015   bool createNewFolder = false;
01016 
01017   TQString _foldername = foldername.stripWhiteSpace();
01018   _foldername = _foldername.replace('\\',""); //try to prevent ESCAPE Sequences
01019 
01020   if ( foldername != mAddMessageLastFolder ) {
01021     createNewFolder = true;
01022     mAddMessageLastFolder = foldername;
01023   }
01024 
01025 
01026   if ( !msgUrl.isEmpty() && msgUrl.isLocalFile() ) {
01027     const TQCString messageText =
01028       KPIM::kFileToString( msgUrl.path(), true, false );
01029     if ( messageText.isEmpty() )
01030       return -2;
01031 
01032     KMMessage *msg = new KMMessage();
01033     msg->fromString( messageText );
01034 
01035     if (createNewFolder) {
01036       if ( foldername.contains("/")) {
01037         TQString tmp_fname = "";
01038         KMFolder *folder = NULL;
01039         KMFolderDir *subfolder;
01040         bool root = true;
01041 
01042         TQStringList subFList = TQStringList::split("/",_foldername,false);
01043 
01044         for ( TQStringList::Iterator it = subFList.begin(); it != subFList.end(); ++it ) {
01045           TQString _newFolder = *it;
01046           if(_newFolder.startsWith(".")) return -1;
01047 
01048           if(root) {
01049             folder = the_folderMgr->findOrCreate(*it, false);
01050             if (folder) {
01051               root = false;
01052               tmp_fname = "/" + *it;
01053             }
01054             else return -1;
01055           } else {
01056             subfolder = folder->createChildFolder();
01057             tmp_fname += "/" + *it;
01058             if(!the_folderMgr->getFolderByURL( tmp_fname )) {
01059               folder = the_folderMgr->createFolder(*it, false, folder->folderType(), subfolder);
01060             }
01061             if(!(folder = the_folderMgr->getFolderByURL( tmp_fname ))) return -1;
01062           }
01063         }
01064 
01065       mAddMsgCurrentFolder = the_folderMgr->getFolderByURL( tmp_fname );
01066       if(!folder) return -1;
01067 
01068       } else {
01069         mAddMsgCurrentFolder = the_folderMgr->findOrCreate(_foldername, false);
01070       }
01071     }
01072 
01073     if ( mAddMsgCurrentFolder ) {
01074       int index;
01075 
01076       if( !MsgStatusFlags.isEmpty() ) {
01077         KMMsgStatus status = strToStatus(MsgStatusFlags);
01078         if (status) msg->setStatus(status);
01079       }
01080 
01081       if ( mAddMsgCurrentFolder->addMsg( msg, &index ) == 0 ) {
01082         mAddMsgCurrentFolder->unGetMsg( index );
01083         retval = 1;
01084       } else {
01085         retval =- 2;
01086         delete msg;
01087         msg = 0;
01088       }
01089     } else {
01090       retval = -1;
01091     }
01092   } else {
01093     retval = -2;
01094   }
01095 
01096   return retval;
01097 }
01098 
01099 void KMKernel::showImportArchiveDialog()
01100 {
01101   KMMainWidget *mainWidget = getKMMainWidget();
01102   KMail::ImportArchiveDialog *importDialog = new KMail::ImportArchiveDialog( mainWidget, WDestructiveClose );
01103   importDialog->setFolder( mainWidget->folderTree()->currentFolder() );
01104   importDialog->show();
01105 }
01106 
01107 TQStringList KMKernel::folderList() const
01108 {
01109   TQStringList folders;
01110   const TQString localPrefix = "/Local";
01111   folders << localPrefix;
01112   the_folderMgr->getFolderURLS( folders, localPrefix );
01113   the_imapFolderMgr->getFolderURLS( folders );
01114   the_dimapFolderMgr->getFolderURLS( folders );
01115   return folders;
01116 }
01117 
01118 DCOPRef KMKernel::getFolder( const TQString& vpath )
01119 {
01120   const TQString localPrefix = "/Local";
01121   if ( the_folderMgr->getFolderByURL( vpath ) )
01122     return DCOPRef( new FolderIface( vpath ) );
01123   else if ( vpath.startsWith( localPrefix ) &&
01124             the_folderMgr->getFolderByURL( vpath.mid( localPrefix.length() ) ) )
01125     return DCOPRef( new FolderIface( vpath.mid( localPrefix.length() ) ) );
01126   else if ( the_imapFolderMgr->getFolderByURL( vpath ) )
01127     return DCOPRef( new FolderIface( vpath ) );
01128   else if ( the_dimapFolderMgr->getFolderByURL( vpath ) )
01129     return DCOPRef( new FolderIface( vpath ) );
01130   return DCOPRef();
01131 }
01132 
01133 void KMKernel::raise()
01134 {
01135   DCOPRef kmail( "kmail", "kmail" );
01136   kmail.call( "newInstance" );
01137 }
01138 
01139 bool KMKernel::showMail( TQ_UINT32 serialNumber, TQString /* messageId */ )
01140 {
01141   KMMainWidget *mainWidget = 0;
01142   if (TDEMainWindow::memberList) {
01143     TDEMainWindow *win = 0;
01144     TQObjectList *l;
01145 
01146     // First look for a TDEMainWindow.
01147     for (win = TDEMainWindow::memberList->first(); win;
01148          win = TDEMainWindow::memberList->next()) {
01149       // Then look for a KMMainWidget.
01150       l = win->queryList("KMMainWidget");
01151       if (l && l->first()) {
01152     mainWidget = dynamic_cast<KMMainWidget *>(l->first());
01153     if (win->isActiveWindow())
01154       break;
01155       }
01156     }
01157   }
01158 
01159   if (mainWidget) {
01160     int idx = -1;
01161     KMFolder *folder = 0;
01162     KMMsgDict::instance()->getLocation(serialNumber, &folder, &idx);
01163     if (!folder || (idx == -1))
01164       return false;
01165     KMFolderOpener openFolder(folder, "showmail");
01166     KMMsgBase *msgBase = folder->getMsgBase(idx);
01167     if (!msgBase)
01168       return false;
01169     bool unGet = !msgBase->isMessage();
01170     KMMessage *msg = folder->getMsg(idx);
01171 
01172     KMReaderMainWin *win = new KMReaderMainWin( false, false );
01173     KMMessage *newMessage = new KMMessage( *msg );
01174     newMessage->setParent( msg->parent() );
01175     newMessage->setMsgSerNum( msg->getMsgSerNum() );
01176     newMessage->setReadyToShow( true );
01177     win->showMsg( GlobalSettings::self()->overrideCharacterEncoding(), newMessage );
01178     win->show();
01179 
01180     if (unGet)
01181       folder->unGetMsg(idx);
01182     return true;
01183   }
01184 
01185   return false;
01186 }
01187 
01188 TQString KMKernel::getFrom( TQ_UINT32 serialNumber )
01189 {
01190   int idx = -1;
01191   KMFolder *folder = 0;
01192   KMMsgDict::instance()->getLocation(serialNumber, &folder, &idx);
01193   if (!folder || (idx == -1))
01194     return TQString();
01195   KMFolderOpener openFolder(folder, "getFrom");
01196   KMMsgBase *msgBase = folder->getMsgBase(idx);
01197   if (!msgBase)
01198     return TQString();
01199   bool unGet = !msgBase->isMessage();
01200   KMMessage *msg = folder->getMsg(idx);
01201   TQString result = msg->from();
01202   if (unGet)
01203     folder->unGetMsg(idx);
01204   return result;
01205 }
01206 
01207 TQString KMKernel::debugScheduler()
01208 {
01209   TQString res = KMail::ActionScheduler::debug();
01210   return res;
01211 }
01212 
01213 TQString KMKernel::debugSernum( TQ_UINT32 serialNumber )
01214 {
01215   TQString res;
01216   if (serialNumber != 0) {
01217     int idx = -1;
01218     KMFolder *folder = 0;
01219     KMMsgBase *msg = 0;
01220     KMMsgDict::instance()->getLocation( serialNumber, &folder, &idx );
01221     // It's possible that the message has been deleted or moved into a
01222     // different folder
01223     if (folder && (idx != -1)) {
01224       // everything is ok
01225       KMFolderOpener openFolder(folder, "debugser");
01226       msg = folder->getMsgBase( idx );
01227       if (msg) {
01228         res.append( TQString( " subject %s,\n sender %s,\n date %s.\n" )
01229                              .arg( msg->subject() )
01230                              .arg( msg->fromStrip() )
01231                              .arg( msg->dateStr() ) );
01232       } else {
01233         res.append( TQString( "Invalid serial number." ) );
01234       }
01235     } else {
01236       res.append( TQString( "Invalid serial number." ) );
01237     }
01238   }
01239   return res;
01240 }
01241 
01242 
01243 void KMKernel::pauseBackgroundJobs()
01244 {
01245   mBackgroundTasksTimer->stop();
01246   mJobScheduler->pause();
01247 }
01248 
01249 void KMKernel::resumeBackgroundJobs()
01250 {
01251   mJobScheduler->resume();
01252   mBackgroundTasksTimer->start( 4 * 60 * 60 * 1000, true );
01253 }
01254 
01255 void KMKernel::stopNetworkJobs()
01256 {
01257   if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Offline )
01258     return;
01259 
01260   GlobalSettings::setNetworkState( GlobalSettings::EnumNetworkState::Offline );
01261   BroadcastStatus::instance()->setStatusMsg( i18n("KMail is set to be offline; all network jobs are suspended"));
01262   emit onlineStatusChanged( (GlobalSettings::EnumNetworkState::type)GlobalSettings::networkState() );
01263 }
01264 
01265 void KMKernel::resumeNetworkJobs()
01266 {
01267   if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Online )
01268     return;
01269 
01270   GlobalSettings::setNetworkState( GlobalSettings::EnumNetworkState::Online );
01271   BroadcastStatus::instance()->setStatusMsg( i18n("KMail is set to be online; all network jobs resumed"));
01272   emit onlineStatusChanged( (GlobalSettings::EnumNetworkState::type)GlobalSettings::networkState() );
01273 
01274   if ( kmkernel->msgSender() && kmkernel->msgSender()->sendImmediate() ) {
01275     kmkernel->msgSender()->sendQueued();
01276   }
01277 }
01278 
01279 bool KMKernel::isOffline()
01280 {
01281   if ( GlobalSettings::self()->networkState() == GlobalSettings::EnumNetworkState::Offline )
01282     return true;
01283   else
01284     return false;
01285 }
01286 
01287 bool KMKernel::askToGoOnline()
01288 {
01289   // already asking means we are offline and need to wait anyhow
01290   if ( s_askingToGoOnline ) {
01291     return false;
01292   }
01293 
01294   if ( kmkernel->isOffline() ) {
01295     s_askingToGoOnline = true;
01296     int rc =
01297     KMessageBox::questionYesNo( KMKernel::self()->mainWin(),
01298                                 i18n("KMail is currently in offline mode. "
01299                                      "How do you want to proceed?"),
01300                                 i18n("Online/Offline"),
01301                                 i18n("Work Online"),
01302                                 i18n("Work Offline"));
01303 
01304     s_askingToGoOnline = false;
01305     if( rc == KMessageBox::No ) {
01306       return false;
01307     } else {
01308       kmkernel->resumeNetworkJobs();
01309     }
01310   }
01311   return true;
01312 }
01313 
01314 /********************************************************************/
01315 /*                        Kernel methods                            */
01316 /********************************************************************/
01317 
01318 void KMKernel::quit()
01319 {
01320   // Called when all windows are closed. Will take care of compacting,
01321   // sending... should handle session management too!!
01322 }
01323   /* TODO later:
01324    Asuming that:
01325      - msgsender is nonblocking
01326        (our own, TQSocketNotifier based. Pops up errors and sends signal
01327         senderFinished when done)
01328 
01329    o If we are getting mail, stop it (but dont lose something!)
01330          [Done already, see mailCheckAborted]
01331    o If we are sending mail, go on UNLESS this was called by SM,
01332        in which case stop ASAP that too (can we warn? should we continue
01333        on next start?)
01334    o If we are compacting, or expunging, go on UNLESS this was SM call.
01335        In that case stop compacting ASAP and continue on next start, before
01336        touching any folders. [Not needed anymore with CompactionJob]
01337 
01338    KMKernel::quit ()
01339    {
01340      SM call?
01341        if compacting, stop;
01342        if sending, stop;
01343        if receiving, stop;
01344        Windows will take care of themselves (composer should dump
01345         its messages, if any but not in deadMail)
01346        declare us ready for the End of the Session
01347 
01348      No, normal quit call
01349        All windows are off. Anything to do, should compact or sender sends?
01350          Yes, maybe put an icon in panel as a sign of life
01351          if sender sending, connect us to his finished slot, declare us ready
01352                             for quit and wait for senderFinished
01353          if not, Folder manager, go compact sent-mail and outbox
01354 }                (= call slotFinished())
01355 
01356 void KMKernel::slotSenderFinished()
01357 {
01358   good, Folder manager go compact sent-mail and outbox
01359   clean up stage1 (release folders and config, unregister from dcop)
01360     -- another kmail may start now ---
01361   kapp->quit();
01362 }
01363 */
01364 
01365 
01366 /********************************************************************/
01367 /*            Init, Exit, and handler  methods                      */
01368 /********************************************************************/
01369 void KMKernel::testDir(const char *_name)
01370 {
01371   TQString foldersPath = TQDir::homeDirPath() + TQString( _name );
01372   TQFileInfo info( foldersPath );
01373   if ( !info.exists() ) {
01374     if ( ::mkdir( TQFile::encodeName( foldersPath ) , S_IRWXU ) == -1 ) {
01375       KMessageBox::sorry(0, i18n("KMail could not create folder '%1';\n"
01376                                  "please make sure that you can view and "
01377                                  "modify the content of the folder '%2'.")
01378                             .arg( foldersPath ).arg( TQDir::homeDirPath() ) );
01379       ::exit(-1);
01380     }
01381   }
01382   if ( !info.isDir() || !info.isReadable() || !info.isWritable() ) {
01383     KMessageBox::sorry(0, i18n("The permissions of the folder '%1' are "
01384                                "incorrect;\n"
01385                                "please make sure that you can view and modify "
01386                                "the content of this folder.")
01387                           .arg( foldersPath ) );
01388     ::exit(-1);
01389   }
01390 }
01391 
01392 
01393 //-----------------------------------------------------------------------------
01394 // Open a composer for each message found in the dead.letter folder
01395 void KMKernel::recoverDeadLetters()
01396 {
01397   TQDir dir( localDataPath() + "autosave/cur" );
01398   if ( !dir.exists() ) {
01399     kdWarning(5006) << "Autosave directory " << dir.path() << " not found!" << endl;
01400     return;
01401   }
01402 
01403   const TQStringList entryList = dir.entryList( TQDir::Files | TQDir::NoSymLinks, TQDir::Unsorted );
01404   for ( unsigned int i = 0; i < entryList.size(); i++ ) {
01405     const TQString fileName = entryList[i];
01406     TQFile file( dir.path() + '/' + fileName );
01407     if ( !file.open( IO_ReadOnly ) ) {
01408       kdWarning(5006) << "Unable to open autosave file " << fileName << endl;
01409       continue;
01410     }
01411     const TQByteArray msgData = file.readAll();
01412     file.close();
01413 
01414     if ( msgData.isEmpty() ) {
01415       kdWarning(5006) << "autosave file " << fileName << " is empty!" << endl;
01416       continue;
01417     }
01418 
01419     KMMessage *msg = new KMMessage(); // Composer will take ownership
01420     msg->fromByteArray( msgData );
01421     KMail::Composer * win = KMail::makeComposer();
01422     win->setMsg( msg, false, false, true );
01423     win->setAutoSaveFilename( fileName );
01424     win->show();
01425   }
01426 }
01427 
01428 //-----------------------------------------------------------------------------
01429 void KMKernel::initFolders(TDEConfig* cfg)
01430 {
01431   TQString name;
01432 
01433   name = cfg->readEntry("inboxFolder");
01434 
01435   // Currently the folder manager cannot manage folders which are not
01436   // in the base folder directory.
01437   //if (name.isEmpty()) name = getenv("MAIL");
01438 
01439   if (name.isEmpty()) name = I18N_NOOP("inbox");
01440 
01441   the_inboxFolder  = (KMFolder*)the_folderMgr->findOrCreate(name);
01442 
01443   if (the_inboxFolder->canAccess() != 0) {
01444     emergencyExit( i18n("You do not have read/write permission to your inbox folder.") );
01445   }
01446 
01447   the_inboxFolder->setSystemFolder(true);
01448   if ( the_inboxFolder->userWhoField().isEmpty() )
01449     the_inboxFolder->setUserWhoField( TQString() );
01450   // inboxFolder->open();
01451 
01452   the_outboxFolder = the_folderMgr->findOrCreate(cfg->readEntry("outboxFolder", I18N_NOOP("outbox")));
01453   if (the_outboxFolder->canAccess() != 0) {
01454     emergencyExit( i18n("You do not have read/write permission to your outbox folder.") );
01455   }
01456   the_outboxFolder->setNoChildren(true);
01457 
01458   the_outboxFolder->setSystemFolder(true);
01459   if ( the_outboxFolder->userWhoField().isEmpty() )
01460     the_outboxFolder->setUserWhoField( TQString() );
01461   /* Nuke the oubox's index file, to make sure that no ghost messages are in
01462    * it from a previous crash. Ghost messages happen in the outbox because it
01463    * the only folder where messages enter and leave within 5 seconds, which is
01464    * the leniency period for index invalidation. Since the number of mails in
01465    * this folder is expected to be very small, we can live with regenerating
01466    * the index on each start to be on the save side. */
01467   //if ( the_outboxFolder->folderType() == KMFolderTypeMaildir )
01468   //  unlink( TQFile::encodeName( the_outboxFolder->indexLocation() ) );
01469   the_outboxFolder->open("kmkernel");
01470 
01471   the_sentFolder = the_folderMgr->findOrCreate(cfg->readEntry("sentFolder", I18N_NOOP("sent-mail")));
01472   if (the_sentFolder->canAccess() != 0) {
01473     emergencyExit( i18n("You do not have read/write permission to your sent-mail folder.") );
01474   }
01475   the_sentFolder->setSystemFolder(true);
01476   if ( the_sentFolder->userWhoField().isEmpty() )
01477     the_sentFolder->setUserWhoField( TQString() );
01478   // the_sentFolder->open();
01479 
01480   the_trashFolder  = the_folderMgr->findOrCreate(cfg->readEntry("trashFolder", I18N_NOOP("trash")));
01481   if (the_trashFolder->canAccess() != 0) {
01482     emergencyExit( i18n("You do not have read/write permission to your trash folder.") );
01483   }
01484   the_trashFolder->setSystemFolder( true );
01485   if ( the_trashFolder->userWhoField().isEmpty() )
01486     the_trashFolder->setUserWhoField( TQString() );
01487   // the_trashFolder->open();
01488 
01489   the_draftsFolder = the_folderMgr->findOrCreate(cfg->readEntry("draftsFolder", I18N_NOOP("drafts")));
01490   if (the_draftsFolder->canAccess() != 0) {
01491     emergencyExit( i18n("You do not have read/write permission to your drafts folder.") );
01492   }
01493   the_draftsFolder->setSystemFolder( true );
01494   if ( the_draftsFolder->userWhoField().isEmpty() )
01495     the_draftsFolder->setUserWhoField( TQString() );
01496   the_draftsFolder->open("kmkernel");
01497 
01498   the_templatesFolder =
01499     the_folderMgr->findOrCreate( cfg->readEntry( "templatesFolder",
01500                                                  I18N_NOOP("templates") ) );
01501   if ( the_templatesFolder->canAccess() != 0 ) {
01502     emergencyExit( i18n("You do not have read/write permission to your templates folder.") );
01503   }
01504   the_templatesFolder->setSystemFolder( true );
01505   if ( the_templatesFolder->userWhoField().isEmpty() )
01506     the_templatesFolder->setUserWhoField( TQString() );
01507   the_templatesFolder->open("kmkernel");
01508 }
01509 
01510 
01511 void KMKernel::init()
01512 {
01513   the_shuttingDown = false;
01514   the_server_is_ready = false;
01515 
01516   TDEConfig* cfg = KMKernel::config();
01517 
01518   TQDir dir;
01519 
01520   TDEConfigGroupSaver saver(cfg, "General");
01521   the_firstStart = cfg->readBoolEntry("first-start", true);
01522   cfg->writeEntry("first-start", false);
01523   the_previousVersion = cfg->readEntry("previous-version");
01524   cfg->writeEntry("previous-version", KMAIL_VERSION);
01525   TQString foldersPath = cfg->readPathEntry( "folders" );
01526   kdDebug(5006) << k_funcinfo << "foldersPath (from config): '" << foldersPath << "'" << endl;
01527 
01528   if ( foldersPath.isEmpty() ) {
01529     foldersPath = localDataPath() + "mail";
01530     if ( transferMail( foldersPath ) ) {
01531       cfg->writePathEntry( "folders", foldersPath );
01532     }
01533     kdDebug(5006) << k_funcinfo << "foldersPath (after transferMail): '" << foldersPath << "'" << endl;
01534   }
01535 
01536   // moved up here because KMMessage::stripOffPrefixes is used below
01537   KMMessage::readConfig();
01538 
01539   the_undoStack     = new UndoStack(20);
01540   the_folderMgr     = new KMFolderMgr(foldersPath);
01541   the_imapFolderMgr = new KMFolderMgr( KMFolderImap::cacheLocation(), KMImapDir);
01542   the_dimapFolderMgr = new KMFolderMgr( KMFolderCachedImap::cacheLocation(), KMDImapDir);
01543   recreateCorruptIndexFiles();
01544 
01545   the_searchFolderMgr = new KMFolderMgr(locateLocal("data","kmail/search"), KMSearchDir);
01546   KMFolder *lsf = the_searchFolderMgr->find( i18n("Last Search") );
01547   if (lsf)
01548     the_searchFolderMgr->remove( lsf );
01549 
01550   the_acctMgr       = new AccountManager();
01551   the_filterMgr     = new KMFilterMgr();
01552   the_popFilterMgr     = new KMFilterMgr(true);
01553   the_filterActionDict = new KMFilterActionDict;
01554 
01555   initFolders(cfg);
01556   the_acctMgr->readConfig();
01557   the_filterMgr->readConfig();
01558   the_popFilterMgr->readConfig();
01559   cleanupImapFolders();
01560 
01561   the_msgSender = new KMSender;
01562   the_server_is_ready = true;
01563   imProxy()->initialize();
01564   { // area for config group "Composer"
01565     TDEConfigGroupSaver saver(cfg, "Composer");
01566     if (cfg->readListEntry("pref-charsets").isEmpty())
01567     {
01568       cfg->writeEntry("pref-charsets", "us-ascii,iso-8859-1,locale,utf-8");
01569     }
01570   }
01571   readConfig();
01572   mICalIface->readConfig();
01573   // filterMgr->dump();
01574 #ifdef HAVE_INDEXLIB
01575   the_msgIndex = new KMMsgIndex(this); //create the indexer
01576 #else
01577   the_msgIndex = 0;
01578 #endif
01579 
01580 //#if 0
01581   the_weaver =  new KPIM::ThreadWeaver::Weaver( this );
01582   the_weaverLogger = new KPIM::ThreadWeaver::WeaverThreadLogger(this);
01583   the_weaverLogger->attach (the_weaver);
01584 //#endif
01585 
01586   connect( the_folderMgr, TQT_SIGNAL( folderRemoved(KMFolder*) ),
01587            this, TQT_SIGNAL( folderRemoved(KMFolder*) ) );
01588   connect( the_dimapFolderMgr, TQT_SIGNAL( folderRemoved(KMFolder*) ),
01589            this, TQT_SIGNAL( folderRemoved(KMFolder*) ) );
01590   connect( the_imapFolderMgr, TQT_SIGNAL( folderRemoved(KMFolder*) ),
01591            this, TQT_SIGNAL( folderRemoved(KMFolder*) ) );
01592   connect( the_searchFolderMgr, TQT_SIGNAL( folderRemoved(KMFolder*) ),
01593            this, TQT_SIGNAL( folderRemoved(KMFolder*) ) );
01594 
01595   mBackgroundTasksTimer = new TQTimer( this, "mBackgroundTasksTimer" );
01596   connect( mBackgroundTasksTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotRunBackgroundTasks() ) );
01597 #ifdef DEBUG_SCHEDULER // for debugging, see jobscheduler.h
01598   mBackgroundTasksTimer->start( 10000, true ); // 10s, singleshot
01599 #else
01600   mBackgroundTasksTimer->start( 5 * 60000, true ); // 5 minutes, singleshot
01601 #endif
01602 
01603   TQTextCodec *codec;
01604   for ( int i = 0; ( codec = TQTextCodec::codecForIndex ( i ) ); i++ ) {
01605     const TQString asciiString( "azAZ19,.-#+!?=()&" );
01606     const TQCString encodedString = codec->fromUnicode( asciiString );
01607     if ( TQString::fromAscii( encodedString ) != asciiString ) {
01608       mNonAsciiCompatibleCodecs.append( codec );
01609     }
01610   }
01611 }
01612 
01613 bool KMKernel::isCodecAsciiCompatible( const TQTextCodec *codec )
01614 {
01615   return !mNonAsciiCompatibleCodecs.contains( codec );
01616 }
01617 
01618 void KMKernel::readConfig()
01619 {
01620   //Needed here, since this function is also called when the configuration
01621   //changes, and the static variables should be updated then - IOF
01622   KMMessage::readConfig();
01623 }
01624 
01625 void KMKernel::cleanupImapFolders()
01626 {
01627   KMAccount *acct = 0;
01628   KMFolderNode *node = the_imapFolderMgr->dir().first();
01629   while (node)
01630   {
01631     if (node->isDir() || ((acct = the_acctMgr->find(node->id()))
01632               && ( acct->type() == "imap" )) )
01633     {
01634       node = the_imapFolderMgr->dir().next();
01635     } else {
01636       KMFolder* folder = static_cast<KMFolder*>(node);
01637       // delete only local
01638       static_cast<KMFolderImap*>( folder->storage() )->setAlreadyRemoved( true );
01639       the_imapFolderMgr->remove(folder);
01640       node = the_imapFolderMgr->dir().first();
01641     }
01642   }
01643 
01644   node = the_dimapFolderMgr->dir().first();
01645   while (node)
01646   {
01647     if (node->isDir() || ((acct = the_acctMgr->find(node->id()))
01648               && ( acct->type() == "cachedimap" )) )
01649     {
01650       node = the_dimapFolderMgr->dir().next();
01651     } else {
01652       the_dimapFolderMgr->remove(static_cast<KMFolder*>(node));
01653       node = the_dimapFolderMgr->dir().first();
01654     }
01655   }
01656 
01657   the_imapFolderMgr->quiet(true);
01658   for (acct = the_acctMgr->first(); acct; acct = the_acctMgr->next())
01659   {
01660     KMFolderImap *fld;
01661     KMAcctImap *imapAcct;
01662 
01663     if (acct->type() != "imap") continue;
01664     fld = static_cast<KMFolderImap*>(the_imapFolderMgr
01665       ->findOrCreate(TQString::number(acct->id()), false, acct->id())->storage());
01666     fld->setNoContent(true);
01667     fld->folder()->setLabel(acct->name());
01668     imapAcct = static_cast<KMAcctImap*>(acct);
01669     fld->setAccount(imapAcct);
01670     imapAcct->setImapFolder(fld);
01671     fld->close( "kernel", true );
01672   }
01673   the_imapFolderMgr->quiet(false);
01674 
01675   the_dimapFolderMgr->quiet( true );
01676   for (acct = the_acctMgr->first(); acct; acct = the_acctMgr->next())
01677   {
01678     KMFolderCachedImap *cfld = 0;
01679     KMAcctCachedImap *cachedImapAcct;
01680 
01681     if (acct->type() != "cachedimap" ) continue;
01682 
01683     KMFolder* fld = the_dimapFolderMgr->find(TQString::number(acct->id()));
01684     if( fld )
01685       cfld = static_cast<KMFolderCachedImap*>( fld->storage() );
01686     if (cfld == 0) {
01687       // Folder doesn't exist yet
01688       cfld = static_cast<KMFolderCachedImap*>(the_dimapFolderMgr->createFolder(TQString::number(acct->id()),
01689             false, KMFolderTypeCachedImap)->storage());
01690       if (!cfld) {
01691         KMessageBox::error(0,(i18n("Cannot create file `%1' in %2.\nKMail cannot start without it.").arg(acct->name()).arg(the_dimapFolderMgr->basePath())));
01692         exit(-1);
01693       }
01694       cfld->folder()->setId( acct->id() );
01695     }
01696 
01697     cfld->setNoContent(true);
01698     cfld->folder()->setLabel(acct->name());
01699     cachedImapAcct = static_cast<KMAcctCachedImap*>(acct);
01700     cfld->setAccount(cachedImapAcct);
01701     cachedImapAcct->setImapFolder(cfld);
01702     cfld->close("kmkernel");
01703   }
01704   the_dimapFolderMgr->quiet( false );
01705 }
01706 
01707 void KMKernel::recreateCorruptIndexFiles()
01708 {
01709   TQValueList<TQGuardedPtr<KMFolder> > folders;
01710   TQValueList<KMFolderIndex*> foldersWithBrokenIndex;
01711   TQStringList strList;
01712   the_folderMgr->createFolderList( &strList, &folders );
01713   the_imapFolderMgr->createFolderList( &strList, &folders );
01714   the_dimapFolderMgr->createFolderList( &strList, &folders );
01715   for ( int i = 0; folders.at(i) != folders.end(); i++ ) {
01716     KMFolder * const folder = *folders.at(i);
01717     if ( !folder || folder->isDir() || folder->isOpened() )
01718       continue;
01719     KMFolderIndex * const index = dynamic_cast<KMFolderIndex*>( folder->storage() );
01720     if ( index && index->indexStatus() != KMFolderIndex::IndexOk ) {
01721       foldersWithBrokenIndex.append( index );
01722     }
01723   }
01724 
01725   if ( !foldersWithBrokenIndex.isEmpty() ) {
01726     TQStringList folderNames;
01727     for ( uint i = 0; i < foldersWithBrokenIndex.size(); i++ ) {
01728       folderNames << foldersWithBrokenIndex[i]->label();
01729     }
01730 
01731     KMessageBox::informationList( 0, i18n( "There is a problem with the mail index of the following "
01732                                            "folders, the indices will now be regenerated.\n"
01733                                            "This can happen because the index files are out of date, missing or corrupted.\n"
01734                                            "Contact your administrator if this happens frequently.\n"
01735                                            "Some information, like status flags, might get lost." ),
01736                                   folderNames, i18n( "Problem with mail indices" ) );
01737 
01738     for ( uint i = 0; i < foldersWithBrokenIndex.size(); i++ ) {
01739       foldersWithBrokenIndex[i]->silentlyRecreateIndex();
01740     }
01741   }
01742 }
01743 
01744 bool KMKernel::doSessionManagement()
01745 {
01746 
01747   // Do session management
01748   if (kapp->isRestored()){
01749     int n = 1;
01750     while (KMMainWin::canBeRestored(n)){
01751       //only restore main windows! (Matthias);
01752       if (KMMainWin::classNameOfToplevel(n) == "KMMainWin")
01753         (new KMMainWin)->restore(n);
01754       n++;
01755     }
01756     return true; // we were restored by SM
01757   }
01758   return false;  // no, we were not restored
01759 }
01760 
01761 void KMKernel::closeAllKMailWindows()
01762 {
01763   if (!TDEMainWindow::memberList) return;
01764   TQPtrListIterator<TDEMainWindow> it(*TDEMainWindow::memberList);
01765   TDEMainWindow *window = 0;
01766   while ((window = it.current()) != 0) {
01767     ++it;
01768     if (window->isA("KMMainWindow") ||
01769     window->inherits("KMail::SecondaryWindow"))
01770       window->close( true ); // close and delete the window
01771   }
01772 }
01773 
01774 void KMKernel::cleanup(void)
01775 {
01776   dumpDeadLetters();
01777   the_shuttingDown = true;
01778   closeAllKMailWindows();
01779 
01780   delete the_acctMgr;
01781   the_acctMgr = 0;
01782   delete the_filterMgr;
01783   the_filterMgr = 0;
01784   delete the_msgSender;
01785   the_msgSender = 0;
01786   delete the_filterActionDict;
01787   the_filterActionDict = 0;
01788   delete the_undoStack;
01789   the_undoStack = 0;
01790   delete the_popFilterMgr;
01791   the_popFilterMgr = 0;
01792 
01793 #if 0
01794   delete the_weaver;
01795   the_weaver = 0;
01796 #endif
01797 
01798   TDEConfig* config =  KMKernel::config();
01799   TDEConfigGroupSaver saver(config, "General");
01800 
01801   if (the_trashFolder) {
01802 
01803     the_trashFolder->close("kmkernel", true);
01804 
01805     if (config->readBoolEntry("empty-trash-on-exit", true))
01806     {
01807       if ( the_trashFolder->count( true ) > 0 )
01808         the_trashFolder->expunge();
01809     }
01810   }
01811 
01812   mICalIface->cleanup();
01813 
01814   TQValueList<TQGuardedPtr<KMFolder> > folders;
01815   TQStringList strList;
01816   KMFolder *folder;
01817   the_folderMgr->createFolderList(&strList, &folders);
01818   for (int i = 0; folders.at(i) != folders.end(); i++)
01819   {
01820     folder = *folders.at(i);
01821     if (!folder || folder->isDir()) continue;
01822     folder->close("kmkernel", true);
01823   }
01824   strList.clear();
01825   folders.clear();
01826   the_searchFolderMgr->createFolderList(&strList, &folders);
01827   for (int i = 0; folders.at(i) != folders.end(); i++)
01828   {
01829     folder = *folders.at(i);
01830     if (!folder || folder->isDir()) continue;
01831     folder->close("kmkernel", true);
01832   }
01833 
01834   delete the_msgIndex;
01835   the_msgIndex = 0;
01836   delete the_folderMgr;
01837   the_folderMgr = 0;
01838   delete the_imapFolderMgr;
01839   the_imapFolderMgr = 0;
01840   delete the_dimapFolderMgr;
01841   the_dimapFolderMgr = 0;
01842   delete the_searchFolderMgr;
01843   the_searchFolderMgr = 0;
01844   delete mConfigureDialog;
01845   mConfigureDialog = 0;
01846   // do not delete, because mWin may point to an existing window
01847   // delete mWin;
01848   mWin = 0;
01849 
01850   if ( RecentAddresses::exists() )
01851     RecentAddresses::self( config )->save( config );
01852   config->sync();
01853 }
01854 
01855 bool KMKernel::transferMail( TQString & destinationDir )
01856 {
01857   TQString dir;
01858 
01859   // check whether the user has a ~/KMail folder
01860   TQFileInfo fi( TQDir::home(), "KMail" );
01861   if ( fi.exists() && fi.isDir() ) {
01862     dir = TQDir::homeDirPath() + "/KMail";
01863     // the following two lines can be removed once moving mail is reactivated
01864     destinationDir = dir;
01865     return true;
01866   }
01867 
01868   if ( dir.isEmpty() ) {
01869     // check whether the user has a ~/Mail folder
01870     fi.setFile( TQDir::home(), "Mail" );
01871     if ( fi.exists() && fi.isDir() &&
01872          TQFile::exists( TQDir::homeDirPath() + "/Mail/.inbox.index" ) ) {
01873       // there's a ~/Mail folder which seems to be used by KMail (because of the
01874       // index file)
01875       dir = TQDir::homeDirPath() + "/Mail";
01876       // the following two lines can be removed once moving mail is reactivated
01877       destinationDir = dir;
01878       return true;
01879     }
01880   }
01881 
01882   if ( dir.isEmpty() ) {
01883     return true; // there's no old mail folder
01884   }
01885 
01886 #if 0
01887   // disabled for now since moving fails in certain cases (e.g. if symbolic links are involved)
01888   const TQString kmailName = kapp->aboutData()->programName();
01889   TQString msg;
01890   if ( TDEIO::NetAccess::exists( destinationDir, true, 0 ) ) {
01891     // if destinationDir exists, we need to warn about possible
01892     // overwriting of files. otherwise, we don't have to
01893     msg = i18n( "%1-%3 is the application name, %4-%7 are folder path",
01894                 "<qt>The <i>%4</i> folder exists. "
01895                 "%1 now uses the <i>%5</i> folder for "
01896                 "its messages.<p>"
01897                 "%2 can move the contents of <i>%6<i> into this folder for "
01898                 "you, though this may replace any existing files with "
01899                 "the same name in <i>%7</i>.<p>"
01900                 "<strong>Would you like %3 to move the mail "
01901                 "files now?</strong></qt>" )
01902           .arg( kmailName, kmailName, kmailName )
01903           .arg( dir, destinationDir, dir, destinationDir );
01904   } else {
01905     msg = i18n( "%1-%3 is the application name, %4-%6 are folder path",
01906                 "<qt>The <i>%4</i> folder exists. "
01907                 "%1 now uses the <i>%5</i> folder for "
01908                 "its messages. %2 can move the contents of <i>%6</i> into "
01909                 "this folder for you.<p>"
01910                 "<strong>Would you like %3 to move the mail "
01911                 "files now?</strong></qt>" )
01912           .arg( kmailName, kmailName, kmailName )
01913           .arg( dir, destinationDir, dir );
01914   }
01915   TQString title = i18n( "Migrate Mail Files?" );
01916   TQString buttonText = i18n( "Move" );
01917 
01918   if ( KMessageBox::questionYesNo( 0, msg, title, buttonText, i18n("Do Not Move") ) ==
01919        KMessageBox::No ) {
01920     destinationDir = dir;
01921     return true;
01922   }
01923 
01924   if ( !TDEIO::NetAccess::move( dir, destinationDir ) ) {
01925     kdDebug(5006) << k_funcinfo << "Moving " << dir << " to " << destinationDir << " failed: " << TDEIO::NetAccess::lastErrorString() << endl;
01926     kdDebug(5006) << k_funcinfo << "Deleting " << destinationDir << endl;
01927     TDEIO::NetAccess::del( destinationDir, 0 );
01928     destinationDir = dir;
01929     return false;
01930   }
01931 #endif
01932 
01933   return true;
01934 }
01935 
01936 
01937 void KMKernel::ungrabPtrKb(void)
01938 {
01939   if(!TDEMainWindow::memberList) return;
01940   TQWidget* widg = TDEMainWindow::memberList->first();
01941   Display* dpy;
01942 
01943   if (!widg) return;
01944   dpy = widg->x11Display();
01945   XUngrabKeyboard(dpy, CurrentTime);
01946   XUngrabPointer(dpy, CurrentTime);
01947 }
01948 
01949 
01950 // Message handler
01951 void KMKernel::kmailMsgHandler(TQtMsgType aType, const char* aMsg)
01952 {
01953   static int recurse=-1;
01954 
01955   recurse++;
01956 
01957   switch (aType)
01958   {
01959   case TQtDebugMsg:
01960   case TQtWarningMsg:
01961     kdDebug(5006) << aMsg << endl;
01962     break;
01963 
01964   case TQtFatalMsg: // Hm, what about using kdFatal() here?
01965     ungrabPtrKb();
01966     kdDebug(5006) << kapp->caption() << " fatal error "
01967           << aMsg << endl;
01968     KMessageBox::error(0, aMsg);
01969     abort();
01970   }
01971 
01972   recurse--;
01973 }
01974 
01975 
01976 void KMKernel::dumpDeadLetters()
01977 {
01978   if ( shuttingDown() )
01979     return; //All documents should be saved before shutting down is set!
01980 
01981   // make all composer windows autosave their contents
01982   if ( !TDEMainWindow::memberList )
01983     return;
01984 
01985   for ( TQPtrListIterator<TDEMainWindow> it(*TDEMainWindow::memberList) ; it.current() != 0; ++it ) {
01986     if ( KMail::Composer * win = ::tqqt_cast<KMail::Composer*>( it.current() ) ) {
01987       win->autoSaveMessage();
01988       // saving the message has to be finished right here, we are called from a dtor,
01989       // therefore we have no chance to finish this later
01990       // yes, this is ugly and potentially dangerous, but the alternative is losing
01991       // currently composed messages...
01992       while ( win->isComposing() )
01993         tqApp->processEvents();
01994     }
01995   }
01996 }
01997 
01998 
01999 
02000 void KMKernel::action(bool mailto, bool check, const TQString &to,
02001                       const TQString &cc, const TQString &bcc,
02002                       const TQString &subj, const TQString &body,
02003                       const KURL &messageFile,
02004                       const KURL::List &attachURLs,
02005                       const QCStringList &customHeaders)
02006 {
02007   if ( mailto )
02008     openComposer( to, cc, bcc, subj, body, 0, messageFile, attachURLs, customHeaders );
02009   else
02010     openReader( check );
02011 
02012   if ( check )
02013     checkMail();
02014   //Anything else?
02015 }
02016 
02017 void KMKernel::byteArrayToRemoteFile(const TQByteArray &aData, const KURL &aURL,
02018   bool overwrite)
02019 {
02020   // ## when KDE 3.3 is out: use TDEIO::storedPut to remove slotDataReq altogether
02021   TDEIO::Job *job = TDEIO::put(aURL, -1, overwrite, false);
02022   putData pd; pd.url = aURL; pd.data = aData; pd.offset = 0;
02023   mPutJobs.insert(job, pd);
02024   connect(job, TQT_SIGNAL(dataReq(TDEIO::Job*,TQByteArray&)),
02025     TQT_SLOT(slotDataReq(TDEIO::Job*,TQByteArray&)));
02026   connect(job, TQT_SIGNAL(result(TDEIO::Job*)),
02027     TQT_SLOT(slotResult(TDEIO::Job*)));
02028 }
02029 
02030 void KMKernel::slotDataReq(TDEIO::Job *job, TQByteArray &data)
02031 {
02032   // send the data in 64 KB chunks
02033   const int MAX_CHUNK_SIZE = 64*1024;
02034   TQMap<TDEIO::Job*, putData>::Iterator it = mPutJobs.find(job);
02035   assert(it != mPutJobs.end());
02036   int remainingBytes = (*it).data.size() - (*it).offset;
02037   if( remainingBytes > MAX_CHUNK_SIZE )
02038   {
02039     // send MAX_CHUNK_SIZE bytes to the receiver (deep copy)
02040     data.duplicate( (*it).data.data() + (*it).offset, MAX_CHUNK_SIZE );
02041     (*it).offset += MAX_CHUNK_SIZE;
02042     //kdDebug( 5006 ) << "Sending " << MAX_CHUNK_SIZE << " bytes ("
02043     //                << remainingBytes - MAX_CHUNK_SIZE << " bytes remain)\n";
02044   }
02045   else
02046   {
02047     // send the remaining bytes to the receiver (deep copy)
02048     data.duplicate( (*it).data.data() + (*it).offset, remainingBytes );
02049     (*it).data = TQByteArray();
02050     (*it).offset = 0;
02051     //kdDebug( 5006 ) << "Sending " << remainingBytes << " bytes\n";
02052   }
02053 }
02054 
02055 void KMKernel::slotResult(TDEIO::Job *job)
02056 {
02057   TQMap<TDEIO::Job*, putData>::Iterator it = mPutJobs.find(job);
02058   assert(it != mPutJobs.end());
02059   if (job->error())
02060   {
02061     if (job->error() == TDEIO::ERR_FILE_ALREADY_EXIST)
02062     {
02063       if (KMessageBox::warningContinueCancel(0,
02064         i18n("File %1 exists.\nDo you want to replace it?")
02065         .arg((*it).url.prettyURL()), i18n("Save to File"), i18n("&Replace"))
02066         == KMessageBox::Continue)
02067         byteArrayToRemoteFile((*it).data, (*it).url, true);
02068     }
02069     else job->showErrorDialog();
02070   }
02071   mPutJobs.remove(it);
02072 }
02073 
02074 void KMKernel::slotRequestConfigSync() {
02075   // ### FIXME: delay as promised in the kdoc of this function ;-)
02076   KMKernel::config()->sync();
02077 }
02078 
02079 void KMKernel::slotShowConfigurationDialog()
02080 {
02081   if( !mConfigureDialog ) {
02082     mConfigureDialog = new ConfigureDialog( 0, "configure", false );
02083     connect( mConfigureDialog, TQT_SIGNAL( configChanged() ),
02084              this, TQT_SLOT( slotConfigChanged() ) );
02085   }
02086 
02087   if( KMKernel::getKMMainWidget() == 0 )
02088   {
02089     // ensure that there is a main widget available
02090     // as parts of the configure dialog (identity) rely on this
02091     // and this slot can be called when there is only a KMComposeWin showing
02092     KMMainWin * win = new KMMainWin;
02093     win->show();
02094   }
02095   if( mConfigureDialog->isHidden() )
02096   {
02097     getKMMainWidget()->headers()->writeConfig();
02098     mConfigureDialog->show();
02099   }
02100   else
02101     mConfigureDialog->raise();
02102 }
02103 
02104 void KMKernel::slotConfigChanged()
02105 {
02106   readConfig();
02107   emit configChanged();
02108 }
02109 
02110 //-------------------------------------------------------------------------------
02111 //static
02112 TQString KMKernel::localDataPath()
02113 {
02114   return locateLocal( "data", "kmail/" );
02115 }
02116 
02117 //-------------------------------------------------------------------------------
02118 
02119 bool KMKernel::haveSystemTrayApplet()
02120 {
02121   return !systemTrayApplets.isEmpty();
02122 }
02123 
02124 bool KMKernel::registerSystemTrayApplet( const KSystemTray* applet )
02125 {
02126   if ( systemTrayApplets.findIndex( applet ) == -1 ) {
02127     systemTrayApplets.append( applet );
02128     return true;
02129   }
02130   else
02131     return false;
02132 }
02133 
02134 bool KMKernel::unregisterSystemTrayApplet( const KSystemTray* applet )
02135 {
02136   TQValueList<const KSystemTray*>::iterator it =
02137     systemTrayApplets.find( applet );
02138   if ( it != systemTrayApplets.end() ) {
02139     systemTrayApplets.remove( it );
02140     return true;
02141   }
02142   else
02143     return false;
02144 }
02145 
02146 void KMKernel::emergencyExit( const TQString& reason )
02147 {
02148   TQString mesg;
02149   if ( reason.length() == 0 ) {
02150     mesg = i18n("KMail encountered a fatal error and will terminate now");
02151   } else {
02152     mesg = i18n("KMail encountered a fatal error and will "
02153                       "terminate now.\nThe error was:\n%1").arg( reason );
02154   }
02155 
02156   kdWarning() << mesg << endl;
02157   KNotifyClient::userEvent( 0, "<qt>"+mesg+"</qt>", KNotifyClient::Messagebox, KNotifyClient::Error );
02158 
02159   ::exit(1);
02160 }
02161 
02165 bool KMKernel::folderIsDraftOrOutbox(const KMFolder * folder)
02166 {
02167   assert( folder );
02168   if ( folder == the_outboxFolder )
02169     return true;
02170   return folderIsDrafts( folder );
02171 }
02172 
02173 bool KMKernel::folderIsDrafts(const KMFolder * folder)
02174 {
02175   assert( folder );
02176   if ( folder == the_draftsFolder )
02177     return true;
02178 
02179   TQString idString = folder->idString();
02180   if ( idString.isEmpty() )
02181     return false;
02182 
02183   // search the identities if the folder matches the drafts-folder
02184   const KPIM::IdentityManager *im = identityManager();
02185   for ( KPIM::IdentityManager::ConstIterator it=im->begin(); it != im->end(); ++it )
02186     if ( (*it).drafts() == idString )
02187       return true;
02188   return false;
02189 }
02190 
02191 bool KMKernel::folderIsTemplates( const KMFolder *folder )
02192 {
02193   assert( folder );
02194   if ( folder == the_templatesFolder )
02195     return true;
02196 
02197   TQString idString = folder->idString();
02198   if ( idString.isEmpty() )
02199     return false;
02200 
02201   // search the identities if the folder matches the templates-folder
02202   const KPIM::IdentityManager *im = identityManager();
02203   for ( KPIM::IdentityManager::ConstIterator it=im->begin(); it != im->end(); ++it )
02204     if ( (*it).templates() == idString )
02205       return true;
02206   return false;
02207 }
02208 
02209 bool KMKernel::folderIsTrash(KMFolder * folder)
02210 {
02211   assert(folder);
02212   if (folder == the_trashFolder) return true;
02213   TQStringList actList = acctMgr()->getAccounts();
02214   TQStringList::Iterator it( actList.begin() );
02215   for( ; it != actList.end() ; ++it ) {
02216     KMAccount* act = acctMgr()->findByName( *it );
02217     if ( act && ( act->trash() == folder->idString() ) )
02218       return true;
02219   }
02220   return false;
02221 }
02222 
02223 bool KMKernel::folderIsSentMailFolder( const KMFolder * folder )
02224 {
02225   assert( folder );
02226   if ( folder == the_sentFolder )
02227     return true;
02228 
02229   TQString idString = folder->idString();
02230   if ( idString.isEmpty() ) return false;
02231 
02232   // search the identities if the folder matches the sent-folder
02233   const KPIM::IdentityManager * im = identityManager();
02234   for( KPIM::IdentityManager::ConstIterator it = im->begin(); it != im->end(); ++it )
02235     if ( (*it).fcc() == idString ) return true;
02236   return false;
02237 }
02238 
02239 KPIM::IdentityManager * KMKernel::identityManager() {
02240   if ( !mIdentityManager ) {
02241     kdDebug(5006) << "instantating KPIM::IdentityManager" << endl;
02242     mIdentityManager = new KPIM::IdentityManager( false, this, "mIdentityManager" );
02243   }
02244   return mIdentityManager;
02245 }
02246 
02247 KMMsgIndex *KMKernel::msgIndex()
02248 {
02249     return the_msgIndex;
02250 }
02251 
02252 TDEMainWindow* KMKernel::mainWin()
02253 {
02254   if (TDEMainWindow::memberList) {
02255     TDEMainWindow *kmWin = 0;
02256 
02257     // First look for a KMMainWin.
02258     for (kmWin = TDEMainWindow::memberList->first(); kmWin;
02259          kmWin = TDEMainWindow::memberList->next())
02260       if (kmWin->isA("KMMainWin"))
02261         return kmWin;
02262 
02263     // There is no KMMainWin. Use any other TDEMainWindow instead (e.g. in
02264     // case we are running inside Kontact) because we anyway only need
02265     // it for modal message boxes and for KNotify events.
02266     kmWin = TDEMainWindow::memberList->first();
02267     if ( kmWin )
02268       return kmWin;
02269   }
02270 
02271   // There's not a single TDEMainWindow. Create a KMMainWin.
02272   // This could happen if we want to pop up an error message
02273   // while we are still doing the startup wizard and no other
02274   // TDEMainWindow is running.
02275   mWin = new KMMainWin;
02276   return mWin;
02277 }
02278 
02279 
02283 void KMKernel::slotEmptyTrash()
02284 {
02285   TQString title = i18n("Empty Trash");
02286   TQString text = i18n("Are you sure you want to empty the trash folders of all accounts?");
02287   if (KMessageBox::warningContinueCancel(0, text, title,
02288                                          KStdGuiItem::cont(), "confirm_empty_trash")
02289       != KMessageBox::Continue)
02290   {
02291     return;
02292   }
02293 
02294   for (KMAccount* acct = acctMgr()->first(); acct; acct = acctMgr()->next())
02295   {
02296     KMFolder* trash = findFolderById(acct->trash());
02297     if (trash)
02298     {
02299       trash->expunge();
02300     }
02301   }
02302 }
02303 
02304 TDEConfig* KMKernel::config()
02305 {
02306   assert(mySelf);
02307   if (!mySelf->mConfig)
02308   {
02309     mySelf->mConfig = TDESharedConfig::openConfig( "kmailrc" );
02310     // Check that all updates have been run on the config file:
02311     KMail::checkConfigUpdates();
02312   }
02313   return mySelf->mConfig;
02314 }
02315 
02316 KMailICalIfaceImpl& KMKernel::iCalIface()
02317 {
02318   assert( mICalIface );
02319   return *mICalIface;
02320 }
02321 
02322 void KMKernel::selectFolder( TQString folderPath )
02323 {
02324   kdDebug(5006)<<"Selecting a folder "<<folderPath<<endl;
02325   const TQString localPrefix = "/Local";
02326   KMFolder *folder = kmkernel->folderMgr()->getFolderByURL( folderPath );
02327   if ( !folder && folderPath.startsWith( localPrefix ) )
02328     folder = the_folderMgr->getFolderByURL( folderPath.mid( localPrefix.length() ) );
02329   if ( !folder )
02330     folder = kmkernel->imapFolderMgr()->getFolderByURL( folderPath );
02331   if ( !folder )
02332     folder = kmkernel->dimapFolderMgr()->getFolderByURL( folderPath );
02333   Q_ASSERT( folder );
02334 
02335   KMMainWidget *widget = getKMMainWidget();
02336   Q_ASSERT( widget );
02337   if ( !widget )
02338     return;
02339 
02340   KMFolderTree *tree = widget->folderTree();
02341   tree->doFolderSelected( tree->indexOfFolder( folder ) );
02342   tree->ensureItemVisible( tree->indexOfFolder( folder ) );
02343 }
02344 
02345 KMMainWidget *KMKernel::getKMMainWidget()
02346 {
02347   //This could definitely use a speadup
02348   TQWidgetList *l = kapp->topLevelWidgets();
02349   TQWidgetListIt it( *l );
02350   TQWidget *wid;
02351 
02352   while ( ( wid = it.current() ) != 0 ) {
02353     ++it;
02354     TQObjectList *l2 = wid->topLevelWidget()->queryList( "KMMainWidget" );
02355     if (l2 && l2->first()) {
02356       KMMainWidget* kmmw = dynamic_cast<KMMainWidget *>( l2->first() );
02357       Q_ASSERT( kmmw );
02358       delete l2;
02359       delete l;
02360       return kmmw;
02361     }
02362     delete l2;
02363   }
02364   delete l;
02365   return 0;
02366 }
02367 
02368 void KMKernel::slotRunBackgroundTasks() // called regularly by timer
02369 {
02370   // Hidden TDEConfig keys. Not meant to be used, but a nice fallback in case
02371   // a stable kmail release goes out with a nasty bug in CompactionJob...
02372   TDEConfigGroup generalGroup( config(), "General" );
02373 
02374   if ( generalGroup.readBoolEntry( "auto-expiring", true ) ) {
02375     the_folderMgr->expireAllFolders( false /*scheduled, not immediate*/ );
02376     the_imapFolderMgr->expireAllFolders( false /*scheduled, not immediate*/ );
02377     the_dimapFolderMgr->expireAllFolders( false /*scheduled, not immediate*/ );
02378     // the_searchFolderMgr: no expiry there
02379   }
02380 
02381   if ( generalGroup.readBoolEntry( "auto-compaction", true ) ) {
02382     the_folderMgr->compactAllFolders( false /*scheduled, not immediate*/ );
02383     // the_imapFolderMgr: no compaction
02384     the_dimapFolderMgr->compactAllFolders( false /*scheduled, not immediate*/ );
02385     // the_searchFolderMgr: no compaction
02386   }
02387 
02388 #ifdef DEBUG_SCHEDULER // for debugging, see jobscheduler.h
02389   mBackgroundTasksTimer->start( 60 * 1000, true ); // check again in 1 minute
02390 #else
02391   mBackgroundTasksTimer->start( 4 * 60 * 60 * 1000, true ); // check again in 4 hours
02392 #endif
02393 
02394 }
02395 
02396 void KMKernel::expireAllFoldersNow() // called by the GUI
02397 {
02398   the_folderMgr->expireAllFolders( true /*immediate*/ );
02399   the_imapFolderMgr->expireAllFolders( true /*immediate*/ );
02400   the_dimapFolderMgr->expireAllFolders( true /*immediate*/ );
02401 }
02402 
02403 void KMKernel::compactAllFolders() // called by the GUI
02404 {
02405   the_folderMgr->compactAllFolders( true /*immediate*/ );
02406   //the_imapFolderMgr->compactAllFolders( true /*immediate*/ );
02407   the_dimapFolderMgr->compactAllFolders( true /*immediate*/ );
02408 }
02409 
02410 KMFolder* KMKernel::findFolderById( const TQString& idString )
02411 {
02412   KMFolder * folder = the_folderMgr->findIdString( idString );
02413   if ( !folder )
02414     folder = the_imapFolderMgr->findIdString( idString );
02415   if ( !folder )
02416     folder = the_dimapFolderMgr->findIdString( idString );
02417   if ( !folder )
02418     folder = the_searchFolderMgr->findIdString( idString );
02419   return folder;
02420 }
02421 
02422 ::KIMProxy* KMKernel::imProxy()
02423 {
02424   return KIMProxy::instance( kapp->dcopClient() );
02425 }
02426 
02427 void KMKernel::enableMailCheck()
02428 {
02429   mMailCheckAborted = false;
02430 }
02431 
02432 bool KMKernel::mailCheckAborted() const
02433 {
02434   return mMailCheckAborted;
02435 }
02436 
02437 void KMKernel::abortMailCheck()
02438 {
02439   mMailCheckAborted = true;
02440 }
02441 
02442 bool KMKernel::canQueryClose()
02443 {
02444   if ( KMMainWidget::mainWidgetList() &&
02445        KMMainWidget::mainWidgetList()->count() > 1 )
02446     return true;
02447   KMMainWidget *widget = getKMMainWidget();
02448   if ( !widget )
02449     return true;
02450   KMSystemTray* systray = widget->systray();
02451   if ( !systray || GlobalSettings::closeDespiteSystemTray() )
02452       return true;
02453   if ( systray->mode() == GlobalSettings::EnumSystemTrayPolicy::ShowAlways ) {
02454     systray->hideKMail();
02455     return false;
02456   } else if ( ( systray->mode() == GlobalSettings::EnumSystemTrayPolicy::ShowOnUnread ) && ( systray->hasUnreadMail() )) {
02457     systray->show();
02458     systray->hideKMail();
02459     return false;
02460   }
02461   return true;
02462 }
02463 
02464 void KMKernel::messageCountChanged()
02465 {
02466   mTimeOfLastMessageCountChange = ::time( 0 );
02467 }
02468 
02469 int KMKernel::timeOfLastMessageCountChange() const
02470 {
02471   return mTimeOfLastMessageCountChange;
02472 }
02473 
02474 bool KMKernel::networkStateConnected()
02475 {
02476 #ifdef __TDE_HAVE_TDEHWLIB
02477   if (mNetworkManager) {
02478     TDENetworkGlobalManagerFlags::TDENetworkGlobalManagerFlags networkStatus = mNetworkManager->backendStatus();
02479     if ((networkStatus & TDENetworkGlobalManagerFlags::Connected)
02480         || (networkStatus & TDENetworkGlobalManagerFlags::BackendUnavailable)
02481         || (networkStatus == TDENetworkGlobalManagerFlags::Unknown)
02482         ){
02483       // Connected or no backend available
02484       return true;
02485     }
02486     else {
02487       // Not connected
02488       return false;
02489     }
02490   }
02491   else {
02492     // Assume connected
02493     return true;
02494   }
02495 #endif
02496  return true;
02497 }
02498 
02499 void KMKernel::slotNetworkStateChanged(TDENetworkConnectionStatus::TDENetworkConnectionStatus, TDENetworkConnectionStatus::TDENetworkConnectionStatus, TQString)
02500 {
02501   if (networkStateConnected()) {
02502     resumeNetworkJobs();
02503   }
02504   else {
02505     stopNetworkJobs();
02506   }
02507 }
02508 
02509 Wallet *KMKernel::wallet() {
02510   static bool walletOpenFailed = false;
02511   if ( mWallet && mWallet->isOpen() )
02512     return mWallet;
02513 
02514   if ( !Wallet::isEnabled() || walletOpenFailed )
02515     return 0;
02516 
02517   // find an appropriate parent window for the wallet dialog
02518   WId window = 0;
02519   if ( tqApp->activeWindow() )
02520     window = tqApp->activeWindow()->winId();
02521   else if ( getKMMainWidget() )
02522     window = getKMMainWidget()->topLevelWidget()->winId();
02523 
02524   delete mWallet;
02525   mWallet = Wallet::openWallet( Wallet::NetworkWallet(), window );
02526 
02527   if ( !mWallet ) {
02528     walletOpenFailed = true;
02529     return 0;
02530   }
02531 
02532   if ( !mWallet->hasFolder( "kmail" ) )
02533     mWallet->createFolder( "kmail" );
02534   mWallet->setFolder( "kmail" );
02535   return mWallet;
02536 }
02537 
02538 TQValueList< TQGuardedPtr<KMFolder> > KMKernel::allFolders()
02539 {
02540   TQStringList names;
02541   TQValueList<TQGuardedPtr<KMFolder> > folders;
02542   folderMgr()->createFolderList(&names, &folders);
02543   imapFolderMgr()->createFolderList(&names, &folders);
02544   dimapFolderMgr()->createFolderList(&names, &folders);
02545   searchFolderMgr()->createFolderList(&names, &folders);
02546 
02547   return folders;
02548 }
02549 
02550 KMFolder *KMKernel::currentFolder() {
02551   KMMainWidget *widget = getKMMainWidget();
02552   KMFolder *folder = 0;
02553   if ( widget && widget->folderTree() ) {
02554     folder = widget->folderTree()->currentFolder();
02555   }
02556   return folder;
02557 }
02558 
02559 // can't be inline, since KMSender isn't known to implement
02560 // KMail::MessageSender outside this .cpp file
02561 KMail::MessageSender * KMKernel::msgSender() { return the_msgSender; }
02562 
02563 #include "kmkernel.moc"