kmail Library API Documentation

kmfilteraction.cpp

00001 // kmfilteraction.cpp
00002 // The process methods really should use an enum instead of an int
00003 // -1 -> status unchanged, 0 -> success, 1 -> failure, 2-> critical failure
00004 // (GoOn),                 (Ok),         (ErrorButGoOn), (CriticalError)
00005 
00006 #ifdef HAVE_CONFIG_H
00007 #include <config.h>
00008 #endif
00009 
00010 #include "kmfilteraction.h"
00011 
00012 #include "kmcommands.h"
00013 #include "kmmsgpart.h"
00014 #include "kmfiltermgr.h"
00015 #include "kmfolderindex.h"
00016 #include "kmfoldermgr.h"
00017 #include "messagesender.h"
00018 #include <libkpimidentities/identity.h>
00019 #include <libkpimidentities/identitymanager.h>
00020 #include <libkpimidentities/identitycombo.h>
00021 #include <libkdepim/kfileio.h>
00022 #include <libkdepim/collectingprocess.h>
00023 using KPIM::CollectingProcess;
00024 #include "kmfawidgets.h"
00025 #include "kmfoldercombobox.h"
00026 #include "kmmsgbase.h"
00027 #include "messageproperty.h"
00028 #include "actionscheduler.h"
00029 using KMail::MessageProperty;
00030 using KMail::ActionScheduler;
00031 #include <kregexp3.h>
00032 #include <ktempfile.h>
00033 #include <kdebug.h>
00034 #include <klocale.h>
00035 #include <kprocess.h>
00036 #include <kaudioplayer.h>
00037 #include <kurlrequester.h>
00038 
00039 #include <qlabel.h>
00040 #include <qlayout.h>
00041 #include <qtextcodec.h>
00042 #include <qtimer.h>
00043 #include <qobject.h>
00044 #include <qstylesheet.h>
00045 #include <assert.h>
00046 
00047 
00048 //=============================================================================
00049 //
00050 // KMFilterAction
00051 //
00052 //=============================================================================
00053 
00054 KMFilterAction::KMFilterAction( const char* aName, const QString aLabel )
00055 {
00056   mName = aName;
00057   mLabel = aLabel;
00058 }
00059 
00060 KMFilterAction::~KMFilterAction()
00061 {
00062 }
00063 
00064 void KMFilterAction::processAsync(KMMessage* msg) const
00065 {
00066   ActionScheduler *handler = MessageProperty::filterHandler( msg );
00067   ReturnCode result = process( msg );
00068   if (handler)
00069     handler->actionMessage( result );
00070 }
00071 
00072 bool KMFilterAction::requiresBody(KMMsgBase*) const
00073 {
00074   return true;
00075 }
00076 
00077 KMFilterAction* KMFilterAction::newAction()
00078 {
00079   return 0;
00080 }
00081 
00082 QWidget* KMFilterAction::createParamWidget(QWidget* parent) const
00083 {
00084   return new QWidget(parent);
00085 }
00086 
00087 void KMFilterAction::applyParamWidgetValue(QWidget*)
00088 {
00089 }
00090 
00091 void KMFilterAction::setParamWidgetValue( QWidget * ) const
00092 {
00093 }
00094 
00095 void KMFilterAction::clearParamWidget( QWidget * ) const
00096 {
00097 }
00098 
00099 bool KMFilterAction::folderRemoved(KMFolder*, KMFolder*)
00100 {
00101   return FALSE;
00102 }
00103 
00104 int KMFilterAction::tempOpenFolder(KMFolder* aFolder)
00105 {
00106   return kmkernel->filterMgr()->tempOpenFolder(aFolder);
00107 }
00108 
00109 void KMFilterAction::sendMDN( KMMessage * msg, KMime::MDN::DispositionType d,
00110                               const QValueList<KMime::MDN::DispositionModifier> & m ) {
00111   if ( !msg ) return;
00112   KMMessage * mdn = msg->createMDN( KMime::MDN::AutomaticAction, d, false, m );
00113   if ( mdn && !kmkernel->msgSender()->send( mdn, FALSE ) ) {
00114     kdDebug(5006) << "KMFilterAction::sendMDN(): sending failed." << endl;
00115     //delete mdn;
00116   }
00117 }
00118 
00119 
00120 //=============================================================================
00121 //
00122 // KMFilterActionWithNone
00123 //
00124 //=============================================================================
00125 
00126 KMFilterActionWithNone::KMFilterActionWithNone( const char* aName, const QString aLabel )
00127   : KMFilterAction( aName, aLabel )
00128 {
00129 }
00130 
00131 
00132 //=============================================================================
00133 //
00134 // KMFilterActionWithUOID
00135 //
00136 //=============================================================================
00137 
00138 KMFilterActionWithUOID::KMFilterActionWithUOID( const char* aName, const QString aLabel )
00139   : KMFilterAction( aName, aLabel ), mParameter( 0 )
00140 {
00141 }
00142 
00143 void KMFilterActionWithUOID::argsFromString( const QString argsStr )
00144 {
00145   mParameter = argsStr.stripWhiteSpace().toUInt();
00146 }
00147 
00148 const QString KMFilterActionWithUOID::argsAsString() const
00149 {
00150   return QString::number( mParameter );
00151 }
00152 
00153 //=============================================================================
00154 //
00155 // KMFilterActionWithString
00156 //
00157 //=============================================================================
00158 
00159 KMFilterActionWithString::KMFilterActionWithString( const char* aName, const QString aLabel )
00160   : KMFilterAction( aName, aLabel )
00161 {
00162 }
00163 
00164 QWidget* KMFilterActionWithString::createParamWidget( QWidget* parent ) const
00165 {
00166   QLineEdit *le = new KLineEdit(parent);
00167   le->setText( mParameter );
00168   return le;
00169 }
00170 
00171 void KMFilterActionWithString::applyParamWidgetValue( QWidget* paramWidget )
00172 {
00173   mParameter = ((QLineEdit*)paramWidget)->text();
00174 }
00175 
00176 void KMFilterActionWithString::setParamWidgetValue( QWidget* paramWidget ) const
00177 {
00178   ((QLineEdit*)paramWidget)->setText( mParameter );
00179 }
00180 
00181 void KMFilterActionWithString::clearParamWidget( QWidget* paramWidget ) const
00182 {
00183   ((QLineEdit*)paramWidget)->clear();
00184 }
00185 
00186 void KMFilterActionWithString::argsFromString( const QString argsStr )
00187 {
00188   mParameter = argsStr;
00189 }
00190 
00191 const QString KMFilterActionWithString::argsAsString() const
00192 {
00193   return mParameter;
00194 }
00195 
00196 //=============================================================================
00197 //
00198 // class KMFilterActionWithStringList
00199 //
00200 //=============================================================================
00201 
00202 KMFilterActionWithStringList::KMFilterActionWithStringList( const char* aName, const QString aLabel )
00203   : KMFilterActionWithString( aName, aLabel )
00204 {
00205 }
00206 
00207 QWidget* KMFilterActionWithStringList::createParamWidget( QWidget* parent ) const
00208 {
00209   QComboBox *cb = new QComboBox( FALSE, parent );
00210   cb->insertStringList( mParameterList );
00211   setParamWidgetValue( cb );
00212   return cb;
00213 }
00214 
00215 void KMFilterActionWithStringList::applyParamWidgetValue( QWidget* paramWidget )
00216 {
00217   mParameter = ((QComboBox*)paramWidget)->currentText();
00218 }
00219 
00220 void KMFilterActionWithStringList::setParamWidgetValue( QWidget* paramWidget ) const
00221 {
00222   int idx = mParameterList.findIndex( mParameter );
00223   ((QComboBox*)paramWidget)->setCurrentItem( idx >= 0 ? idx : 0 );
00224 }
00225 
00226 void KMFilterActionWithStringList::clearParamWidget( QWidget* paramWidget ) const
00227 {
00228   ((QComboBox*)paramWidget)->setCurrentItem(0);
00229 }
00230 
00231 void KMFilterActionWithStringList::argsFromString( const QString argsStr )
00232 {
00233   int idx = mParameterList.findIndex( argsStr );
00234   if ( idx < 0 ) {
00235     mParameterList.append( argsStr );
00236     idx = mParameterList.count() - 1;
00237   }
00238   mParameter = *mParameterList.at( idx );
00239 }
00240 
00241 
00242 //=============================================================================
00243 //
00244 // class KMFilterActionWithFolder
00245 //
00246 //=============================================================================
00247 
00248 KMFilterActionWithFolder::KMFilterActionWithFolder( const char* aName, const QString aLabel )
00249   : KMFilterAction( aName, aLabel )
00250 {
00251   mFolder = 0;
00252 }
00253 
00254 QWidget* KMFilterActionWithFolder::createParamWidget( QWidget* parent ) const
00255 {
00256   KMFolderComboBox *cb = new KMFolderComboBox( parent );
00257   cb->showImapFolders( false );
00258   setParamWidgetValue( cb );
00259   return cb;
00260 }
00261 
00262 void KMFilterActionWithFolder::applyParamWidgetValue( QWidget* paramWidget )
00263 {
00264   mFolder = ((KMFolderComboBox *)paramWidget)->getFolder();
00265   if (mFolder)
00266   {
00267      mFolderName = QString::null;
00268   }
00269   else
00270   {
00271      mFolderName = ((KMFolderComboBox *)paramWidget)->currentText();
00272   }
00273 }
00274 
00275 void KMFilterActionWithFolder::setParamWidgetValue( QWidget* paramWidget ) const
00276 {
00277   if ( mFolder )
00278     ((KMFolderComboBox *)paramWidget)->setFolder( mFolder );
00279   else
00280     ((KMFolderComboBox *)paramWidget)->setFolder( mFolderName );
00281 }
00282 
00283 void KMFilterActionWithFolder::clearParamWidget( QWidget* paramWidget ) const
00284 {
00285   ((KMFolderComboBox *)paramWidget)->setFolder( kmkernel->draftsFolder() );
00286 }
00287 
00288 void KMFilterActionWithFolder::argsFromString( const QString argsStr )
00289 {
00290   mFolder = kmkernel->folderMgr()->findIdString( argsStr );
00291   if (!mFolder)
00292      mFolder = kmkernel->dimapFolderMgr()->findIdString( argsStr );
00293   if (mFolder)
00294      mFolderName = QString::null;
00295   else
00296      mFolderName = argsStr;
00297 }
00298 
00299 const QString KMFilterActionWithFolder::argsAsString() const
00300 {
00301   QString result;
00302   if ( mFolder )
00303     result = mFolder->idString();
00304   else
00305     result = mFolderName;
00306   return result;
00307 }
00308 
00309 const QString KMFilterActionWithFolder::displayString() const
00310 {
00311   QString result;
00312   if ( mFolder )
00313     result = mFolder->prettyURL();
00314   else
00315     result = mFolderName;
00316   return label() + " \"" + QStyleSheet::escape( result ) + "\"";
00317 }
00318 
00319 bool KMFilterActionWithFolder::folderRemoved( KMFolder* aFolder, KMFolder* aNewFolder )
00320 {
00321   if ( aFolder == mFolder ) {
00322     mFolder = aNewFolder;
00323     if ( aNewFolder )
00324       mFolderName = QString::null;
00325     else
00326       mFolderName = i18n( "<select a folder>" );
00327     return TRUE;
00328   } else
00329     return FALSE;
00330 }
00331 
00332 //=============================================================================
00333 //
00334 // class KMFilterActionWithAddress
00335 //
00336 //=============================================================================
00337 
00338 KMFilterActionWithAddress::KMFilterActionWithAddress( const char* aName, const QString aLabel )
00339   : KMFilterActionWithString( aName, aLabel )
00340 {
00341 }
00342 
00343 QWidget* KMFilterActionWithAddress::createParamWidget( QWidget* parent ) const
00344 {
00345   KMFilterActionWithAddressWidget *w = new KMFilterActionWithAddressWidget(parent);
00346   w->setText( mParameter );
00347   return w;
00348 }
00349 
00350 void KMFilterActionWithAddress::applyParamWidgetValue( QWidget* paramWidget )
00351 {
00352   mParameter = ((KMFilterActionWithAddressWidget*)paramWidget)->text();
00353 }
00354 
00355 void KMFilterActionWithAddress::setParamWidgetValue( QWidget* paramWidget ) const
00356 {
00357   ((KMFilterActionWithAddressWidget*)paramWidget)->setText( mParameter );
00358 }
00359 
00360 void KMFilterActionWithAddress::clearParamWidget( QWidget* paramWidget ) const
00361 {
00362   ((KMFilterActionWithAddressWidget*)paramWidget)->clear();
00363 }
00364 
00365 //=============================================================================
00366 //
00367 // class KMFilterActionWithCommand
00368 //
00369 //=============================================================================
00370 
00371 KMFilterActionWithCommand::KMFilterActionWithCommand( const char* aName, const QString aLabel )
00372   : KMFilterActionWithUrl( aName, aLabel )
00373 {
00374 }
00375 
00376 QWidget* KMFilterActionWithCommand::createParamWidget( QWidget* parent ) const
00377 {
00378   return KMFilterActionWithUrl::createParamWidget( parent );
00379 }
00380 
00381 void KMFilterActionWithCommand::applyParamWidgetValue( QWidget* paramWidget )
00382 {
00383   KMFilterActionWithUrl::applyParamWidgetValue( paramWidget );
00384 }
00385 
00386 void KMFilterActionWithCommand::setParamWidgetValue( QWidget* paramWidget ) const
00387 {
00388   KMFilterActionWithUrl::setParamWidgetValue( paramWidget );
00389 }
00390 
00391 void KMFilterActionWithCommand::clearParamWidget( QWidget* paramWidget ) const
00392 {
00393   KMFilterActionWithUrl::clearParamWidget( paramWidget );
00394 }
00395 
00396 QString KMFilterActionWithCommand::substituteCommandLineArgsFor( KMMessage *aMsg, QPtrList<KTempFile> & aTempFileList ) const
00397 {
00398   QString result = mParameter;
00399   QValueList<int> argList;
00400   QRegExp r( "%[0-9-]+" );
00401 
00402   // search for '%n'
00403   int start = -1;
00404   while ( ( start = r.search( result, start + 1 ) ) > 0 ) {
00405     int len = r.matchedLength();
00406     // and save the encountered 'n' in a list.
00407     bool OK = false;
00408     int n = result.mid( start + 1, len - 1 ).toInt( &OK );
00409     if ( OK )
00410       argList.append( n );
00411   }
00412 
00413   // sort the list of n's
00414   qHeapSort( argList );
00415 
00416   // and use QString::arg to substitute filenames for the %n's.
00417   int lastSeen = -2;
00418   QString tempFileName;
00419   for ( QValueList<int>::Iterator it = argList.begin() ; it != argList.end() ; ++it ) {
00420     // setup temp files with check for duplicate %n's
00421     if ( (*it) != lastSeen ) {
00422       KTempFile *tf = new KTempFile();
00423       if ( tf->status() != 0 ) {
00424         tf->close();
00425         delete tf;
00426         kdDebug(5006) << "KMFilterActionWithCommand: Could not create temp file!" << endl;
00427         return QString::null;
00428       }
00429       tf->setAutoDelete(TRUE);
00430       aTempFileList.append( tf );
00431       tempFileName = tf->name();
00432       if ((*it) == -1)
00433         KPIM::kCStringToFile( aMsg->asString(), tempFileName, //###
00434                           false, false, false );
00435       else if (aMsg->numBodyParts() == 0)
00436         KPIM::kByteArrayToFile( aMsg->bodyDecodedBinary(), tempFileName,
00437                           false, false, false );
00438       else {
00439         KMMessagePart msgPart;
00440         aMsg->bodyPart( (*it), &msgPart );
00441         KPIM::kByteArrayToFile( msgPart.bodyDecodedBinary(), tempFileName,
00442                           false, false, false );
00443       }
00444       tf->close();
00445     }
00446     // QString( "%0 and %1 and %1" ).arg( 0 ).arg( 1 )
00447     // returns "0 and 1 and %1", so we must call .arg as
00448     // many times as there are %n's, regardless of their multiplicity.
00449     if ((*it) == -1) result.replace( "%-1", tempFileName );
00450     else result = result.arg( tempFileName );
00451   }
00452 
00453   // And finally, replace the %{foo} with the content of the foo
00454   // header field:
00455   QRegExp header_rx( "%\\{([a-z0-9-]+)\\}", false );
00456   int idx = 0;
00457   while ( ( idx = header_rx.search( result, idx ) ) != -1 ) {
00458     QString replacement = KProcess::quote( aMsg->headerField( header_rx.cap(1).latin1() ) );
00459     result.replace( idx, header_rx.matchedLength(), replacement );
00460     idx += replacement.length();
00461   }
00462 
00463   return result;
00464 }
00465 
00466 
00467 KMFilterAction::ReturnCode KMFilterActionWithCommand::genericProcess(KMMessage* aMsg, bool withOutput) const
00468 {
00469   Q_ASSERT( aMsg );
00470 
00471   if ( mParameter.isEmpty() )
00472     return ErrorButGoOn;
00473 
00474   // KProcess doesn't support a QProcess::launch() equivalent, so
00475   // we must use a temp file :-(
00476   KTempFile * inFile = new KTempFile;
00477   inFile->setAutoDelete(TRUE);
00478 
00479   QPtrList<KTempFile> atmList;
00480   atmList.setAutoDelete(TRUE);
00481   atmList.append( inFile );
00482 
00483   QString commandLine = substituteCommandLineArgsFor( aMsg , atmList );
00484   if ( commandLine.isEmpty() )
00485     return ErrorButGoOn;
00486 
00487   // The parentheses force the creation of a subshell
00488   // in which the user-specified command is executed.
00489   // This is to really catch all output of the command as well
00490   // as to avoid clashes of our redirection with the ones
00491   // the user may have specified. In the long run, we
00492   // shouldn't be using tempfiles at all for this class, due
00493   // to security aspects. (mmutz)
00494   commandLine =  "(" + commandLine + ") <" + inFile->name();
00495 
00496   // write message to file
00497   QString tempFileName = inFile->name();
00498   KPIM::kCStringToFile( aMsg->asString(), tempFileName, //###
00499                   false, false, false );
00500   inFile->close();
00501 
00502   CollectingProcess shProc;
00503   shProc.setUseShell(true);
00504   shProc << commandLine;
00505 
00506   // run process:
00507   if ( !shProc.start( KProcess::Block,
00508                       withOutput ? KProcess::Stdout
00509                                  : KProcess::NoCommunication ) )
00510     return ErrorButGoOn;
00511 
00512   if ( !shProc.normalExit() || shProc.exitStatus() != 0 ) {
00513     return ErrorButGoOn;
00514   }
00515 
00516   if ( withOutput ) {
00517     // read altered message:
00518     QByteArray msgText = shProc.collectedStdout();
00519 
00520     if ( !msgText.isEmpty() ) {
00521     /* If the pipe through alters the message, it could very well
00522        happen that it no longer has a X-UID header afterwards. That is
00523        unfortunate, as we need to removed the original from the folder
00524        using that, and look it up in the message. When the (new) message
00525        is uploaded, the header is stripped anyhow. */
00526       QString uid = aMsg->headerField("X-UID");
00527       aMsg->fromByteArray( msgText );
00528       aMsg->setHeaderField("X-UID",uid);
00529     }
00530     else
00531       return ErrorButGoOn;
00532   }
00533   return GoOn;
00534 }
00535 
00536 
00537 //=============================================================================
00538 //
00539 //   Specific  Filter  Actions
00540 //
00541 //=============================================================================
00542 
00543 //=============================================================================
00544 // KMFilterActionBounce - bounce
00545 // Return mail as undelivered.
00546 //=============================================================================
00547 class KMFilterActionBounce : public KMFilterActionWithNone
00548 {
00549 public:
00550   KMFilterActionBounce();
00551   virtual ReturnCode process(KMMessage* msg) const;
00552   static KMFilterAction* newAction(void);
00553 };
00554 
00555 KMFilterAction* KMFilterActionBounce::newAction(void)
00556 {
00557   return (new KMFilterActionBounce);
00558 }
00559 
00560 KMFilterActionBounce::KMFilterActionBounce()
00561   : KMFilterActionWithNone( "bounce", i18n("Bounce") )
00562 {
00563 }
00564 
00565 KMFilterAction::ReturnCode KMFilterActionBounce::process(KMMessage* msg) const
00566 {
00567   KMMessage *bounceMsg = msg->createBounce( FALSE );
00568   if ( !bounceMsg ) return ErrorButGoOn;
00569 
00570   // Queue message. This is a) so that the user can check
00571   // the bounces before sending and b) for speed reasons.
00572   kmkernel->msgSender()->send( bounceMsg, FALSE );
00573 
00574   return GoOn;
00575 }
00576 
00577 
00578 //=============================================================================
00579 // KMFilterActionSendReceipt - send receipt
00580 // Return delivery receipt.
00581 //=============================================================================
00582 class KMFilterActionSendReceipt : public KMFilterActionWithNone
00583 {
00584 public:
00585   KMFilterActionSendReceipt();
00586   virtual ReturnCode process(KMMessage* msg) const;
00587   static KMFilterAction* newAction(void);
00588 };
00589 
00590 KMFilterAction* KMFilterActionSendReceipt::newAction(void)
00591 {
00592   return (new KMFilterActionSendReceipt);
00593 }
00594 
00595 KMFilterActionSendReceipt::KMFilterActionSendReceipt()
00596   : KMFilterActionWithNone( "confirm delivery", i18n("Confirm Delivery") )
00597 {
00598 }
00599 
00600 KMFilterAction::ReturnCode KMFilterActionSendReceipt::process(KMMessage* msg) const
00601 {
00602   KMMessage *receipt = msg->createDeliveryReceipt();
00603   if ( !receipt ) return ErrorButGoOn;
00604 
00605   // Queue message. This is a) so that the user can check
00606   // the receipt before sending and b) for speed reasons.
00607   kmkernel->msgSender()->send( receipt, FALSE );
00608 
00609   return GoOn;
00610 }
00611 
00612 
00613 
00614 //=============================================================================
00615 // KMFilterActionSetTransport - set transport to...
00616 // Specify mail transport (smtp server) to be used when replying to a message
00617 //=============================================================================
00618 class KMFilterActionTransport: public KMFilterActionWithString
00619 {
00620 public:
00621   KMFilterActionTransport();
00622   virtual ReturnCode process(KMMessage* msg) const;
00623   static KMFilterAction* newAction(void);
00624 };
00625 
00626 KMFilterAction* KMFilterActionTransport::newAction(void)
00627 {
00628   return (new KMFilterActionTransport);
00629 }
00630 
00631 KMFilterActionTransport::KMFilterActionTransport()
00632   : KMFilterActionWithString( "set transport", i18n("Set Transport To") )
00633 {
00634 }
00635 
00636 KMFilterAction::ReturnCode KMFilterActionTransport::process(KMMessage* msg) const
00637 {
00638   if ( mParameter.isEmpty() )
00639     return ErrorButGoOn;
00640   msg->setHeaderField( "X-KMail-Transport", mParameter );
00641   return GoOn;
00642 }
00643 
00644 
00645 //=============================================================================
00646 // KMFilterActionReplyTo - set Reply-To to
00647 // Set the Reply-to header in a message
00648 //=============================================================================
00649 class KMFilterActionReplyTo: public KMFilterActionWithString
00650 {
00651 public:
00652   KMFilterActionReplyTo();
00653   virtual ReturnCode process(KMMessage* msg) const;
00654   static KMFilterAction* newAction(void);
00655 };
00656 
00657 KMFilterAction* KMFilterActionReplyTo::newAction(void)
00658 {
00659   return (new KMFilterActionReplyTo);
00660 }
00661 
00662 KMFilterActionReplyTo::KMFilterActionReplyTo()
00663   : KMFilterActionWithString( "set Reply-To", i18n("Set Reply-To To") )
00664 {
00665   mParameter = "";
00666 }
00667 
00668 KMFilterAction::ReturnCode KMFilterActionReplyTo::process(KMMessage* msg) const
00669 {
00670   msg->setHeaderField( "Reply-To", mParameter );
00671   return GoOn;
00672 }
00673 
00674 
00675 
00676 //=============================================================================
00677 // KMFilterActionIdentity - set identity to
00678 // Specify Identity to be used when replying to a message
00679 //=============================================================================
00680 class KMFilterActionIdentity: public KMFilterActionWithUOID
00681 {
00682 public:
00683   KMFilterActionIdentity();
00684   virtual ReturnCode process(KMMessage* msg) const;
00685   static KMFilterAction* newAction();
00686 
00687   QWidget * createParamWidget( QWidget * parent ) const;
00688   void applyParamWidgetValue( QWidget * parent );
00689   void setParamWidgetValue( QWidget * parent ) const;
00690   void clearParamWidget( QWidget * param ) const;
00691 };
00692 
00693 KMFilterAction* KMFilterActionIdentity::newAction()
00694 {
00695   return (new KMFilterActionIdentity);
00696 }
00697 
00698 KMFilterActionIdentity::KMFilterActionIdentity()
00699   : KMFilterActionWithUOID( "set identity", i18n("Set Identity To") )
00700 {
00701   mParameter = kmkernel->identityManager()->defaultIdentity().uoid();
00702 }
00703 
00704 KMFilterAction::ReturnCode KMFilterActionIdentity::process(KMMessage* msg) const
00705 {
00706   msg->setHeaderField( "X-KMail-Identity", QString::number( mParameter ) );
00707   return GoOn;
00708 }
00709 
00710 QWidget * KMFilterActionIdentity::createParamWidget( QWidget * parent ) const
00711 {
00712   KPIM::IdentityCombo * ic = new KPIM::IdentityCombo( kmkernel->identityManager(), parent );
00713   ic->setCurrentIdentity( mParameter );
00714   return ic;
00715 }
00716 
00717 void KMFilterActionIdentity::applyParamWidgetValue( QWidget * paramWidget )
00718 {
00719   KPIM::IdentityCombo * ic = dynamic_cast<KPIM::IdentityCombo*>( paramWidget );
00720   assert( ic );
00721   mParameter = ic->currentIdentity();
00722 }
00723 
00724 void KMFilterActionIdentity::clearParamWidget( QWidget * paramWidget ) const
00725 {
00726   KPIM::IdentityCombo * ic = dynamic_cast<KPIM::IdentityCombo*>( paramWidget );
00727   assert( ic );
00728   ic->setCurrentItem( 0 );
00729   //ic->setCurrentIdentity( kmkernel->identityManager()->defaultIdentity() );
00730 }
00731 
00732 void KMFilterActionIdentity::setParamWidgetValue( QWidget * paramWidget ) const
00733 {
00734   KPIM::IdentityCombo * ic = dynamic_cast<KPIM::IdentityCombo*>( paramWidget );
00735   assert( ic );
00736   ic->setCurrentIdentity( mParameter );
00737 }
00738 
00739 //=============================================================================
00740 // KMFilterActionSetStatus - set status to
00741 // Set the status of messages
00742 //=============================================================================
00743 class KMFilterActionSetStatus: public KMFilterActionWithStringList
00744 {
00745 public:
00746   KMFilterActionSetStatus();
00747   virtual ReturnCode process(KMMessage* msg) const;
00748   virtual bool requiresBody(KMMsgBase*) const;
00749 
00750   static KMFilterAction* newAction();
00751 
00752   virtual bool isEmpty() const { return false; }
00753 
00754   virtual void argsFromString( const QString argsStr );
00755   virtual const QString argsAsString() const;
00756 };
00757 
00758 
00759 static const KMMsgStatus stati[] =
00760 {
00761   KMMsgStatusFlag,
00762   KMMsgStatusRead,
00763   KMMsgStatusUnread,
00764   KMMsgStatusReplied,
00765   KMMsgStatusForwarded,
00766   KMMsgStatusOld,
00767   KMMsgStatusNew,
00768   KMMsgStatusWatched,
00769   KMMsgStatusIgnored,
00770   KMMsgStatusSpam,
00771   KMMsgStatusHam
00772 };
00773 static const int StatiCount = sizeof( stati ) / sizeof( KMMsgStatus );
00774 
00775 KMFilterAction* KMFilterActionSetStatus::newAction()
00776 {
00777   return (new KMFilterActionSetStatus);
00778 }
00779 
00780 KMFilterActionSetStatus::KMFilterActionSetStatus()
00781   : KMFilterActionWithStringList( "set status", i18n("Mark As") )
00782 {
00783   // if you change this list, also update
00784   // KMFilterActionSetStatus::stati above
00785   mParameterList.append( "" );
00786   mParameterList.append( i18n("msg status","Important") );
00787   mParameterList.append( i18n("msg status","Read") );
00788   mParameterList.append( i18n("msg status","Unread") );
00789   mParameterList.append( i18n("msg status","Replied") );
00790   mParameterList.append( i18n("msg status","Forwarded") );
00791   mParameterList.append( i18n("msg status","Old") );
00792   mParameterList.append( i18n("msg status","New") );
00793   mParameterList.append( i18n("msg status","Watched") );
00794   mParameterList.append( i18n("msg status","Ignored") );
00795   mParameterList.append( i18n("msg status","Spam") );
00796   mParameterList.append( i18n("msg status","Ham") );
00797 
00798   mParameter = *mParameterList.at(0);
00799 }
00800 
00801 KMFilterAction::ReturnCode KMFilterActionSetStatus::process(KMMessage* msg) const
00802 {
00803   int idx = mParameterList.findIndex( mParameter );
00804   if ( idx < 1 ) return ErrorButGoOn;
00805 
00806   KMMsgStatus status = stati[idx-1] ;
00807   msg->setStatus( status );
00808   return GoOn;
00809 }
00810 
00811 bool KMFilterActionSetStatus::requiresBody(KMMsgBase*) const
00812 {
00813   return false;
00814 }
00815 
00816 void KMFilterActionSetStatus::argsFromString( const QString argsStr )
00817 {
00818   if ( argsStr.length() == 1 ) {
00819     for ( int i = 0 ; i < StatiCount ; i++ )
00820       if ( KMMsgBase::statusToStr(stati[i])[0] == argsStr[0] ) {
00821         mParameter = *mParameterList.at(i+1);
00822         return;
00823       }
00824   }
00825   mParameter = *mParameterList.at(0);
00826 }
00827 
00828 const QString KMFilterActionSetStatus::argsAsString() const
00829 {
00830   int idx = mParameterList.findIndex( mParameter );
00831   if ( idx < 1 ) return QString::null;
00832 
00833   KMMsgStatus status = stati[idx-1];
00834   return KMMsgBase::statusToStr(status);
00835 }
00836 
00837 
00838 //=============================================================================
00839 // KMFilterActionFakeDisposition - send fake MDN
00840 // Sends a fake MDN or forces an ignore.
00841 //=============================================================================
00842 class KMFilterActionFakeDisposition: public KMFilterActionWithStringList
00843 {
00844 public:
00845   KMFilterActionFakeDisposition();
00846   virtual ReturnCode process(KMMessage* msg) const;
00847   static KMFilterAction* newAction() {
00848     return (new KMFilterActionFakeDisposition);
00849   }
00850 
00851   virtual bool isEmpty() const { return false; }
00852 
00853   virtual void argsFromString( const QString argsStr );
00854   virtual const QString argsAsString() const;
00855 };
00856 
00857 
00858 // if you change this list, also update
00859 // the count in argsFromString
00860 static const KMime::MDN::DispositionType mdns[] =
00861 {
00862   KMime::MDN::Displayed,
00863   KMime::MDN::Deleted,
00864   KMime::MDN::Dispatched,
00865   KMime::MDN::Processed,
00866   KMime::MDN::Denied,
00867   KMime::MDN::Failed,
00868 };
00869 static const int numMDNs = sizeof mdns / sizeof *mdns;
00870 
00871 
00872 KMFilterActionFakeDisposition::KMFilterActionFakeDisposition()
00873   : KMFilterActionWithStringList( "fake mdn", i18n("Send Fake MDN") )
00874 {
00875   // if you change this list, also update
00876   // mdns above
00877   mParameterList.append( "" );
00878   mParameterList.append( i18n("MDN type","Ignore") );
00879   mParameterList.append( i18n("MDN type","Displayed") );
00880   mParameterList.append( i18n("MDN type","Deleted") );
00881   mParameterList.append( i18n("MDN type","Dispatched") );
00882   mParameterList.append( i18n("MDN type","Processed") );
00883   mParameterList.append( i18n("MDN type","Denied") );
00884   mParameterList.append( i18n("MDN type","Failed") );
00885 
00886   mParameter = *mParameterList.at(0);
00887 }
00888 
00889 KMFilterAction::ReturnCode KMFilterActionFakeDisposition::process(KMMessage* msg) const
00890 {
00891   int idx = mParameterList.findIndex( mParameter );
00892   if ( idx < 1 ) return ErrorButGoOn;
00893 
00894   if ( idx == 1 ) // ignore
00895     msg->setMDNSentState( KMMsgMDNIgnore );
00896   else // send
00897     sendMDN( msg, mdns[idx-2] ); // skip first two entries: "" and "ignore"
00898   return GoOn;
00899 }
00900 
00901 void KMFilterActionFakeDisposition::argsFromString( const QString argsStr )
00902 {
00903   if ( argsStr.length() == 1 ) {
00904     if ( argsStr[0] == 'I' ) { // ignore
00905       mParameter = *mParameterList.at(1);
00906       return;
00907     }
00908     for ( int i = 0 ; i < numMDNs ; i++ )
00909       if ( char(mdns[i]) == argsStr[0] ) { // send
00910         mParameter = *mParameterList.at(i+2);
00911         return;
00912       }
00913   }
00914   mParameter = *mParameterList.at(0);
00915 }
00916 
00917 const QString KMFilterActionFakeDisposition::argsAsString() const
00918 {
00919   int idx = mParameterList.findIndex( mParameter );
00920   if ( idx < 1 ) return QString::null;
00921 
00922   return QString( QChar( idx < 2 ? 'I' : char(mdns[idx-2]) ) );
00923 }
00924 
00925 
00926 //=============================================================================
00927 // KMFilterActionRemoveHeader - remove header
00928 // Remove all instances of the given header field.
00929 //=============================================================================
00930 class KMFilterActionRemoveHeader: public KMFilterActionWithStringList
00931 {
00932 public:
00933   KMFilterActionRemoveHeader();
00934   virtual ReturnCode process(KMMessage* msg) const;
00935   virtual QWidget* createParamWidget( QWidget* parent ) const;
00936   virtual void setParamWidgetValue( QWidget* paramWidget ) const;
00937 
00938   static KMFilterAction* newAction();
00939 };
00940 
00941 KMFilterAction* KMFilterActionRemoveHeader::newAction()
00942 {
00943   return (new KMFilterActionRemoveHeader);
00944 }
00945 
00946 KMFilterActionRemoveHeader::KMFilterActionRemoveHeader()
00947   : KMFilterActionWithStringList( "remove header", i18n("Remove Header") )
00948 {
00949   mParameterList << ""
00950                  << "Reply-To"
00951                  << "Delivered-To"
00952                  << "X-KDE-PR-Message"
00953                  << "X-KDE-PR-Package"
00954                  << "X-KDE-PR-Keywords";
00955   mParameter = *mParameterList.at(0);
00956 }
00957 
00958 QWidget* KMFilterActionRemoveHeader::createParamWidget( QWidget* parent ) const
00959 {
00960   QComboBox *cb = new QComboBox( TRUE/*editable*/, parent );
00961   cb->setInsertionPolicy( QComboBox::AtBottom );
00962   setParamWidgetValue( cb );
00963   return cb;
00964 }
00965 
00966 KMFilterAction::ReturnCode KMFilterActionRemoveHeader::process(KMMessage* msg) const
00967 {
00968   if ( mParameter.isEmpty() ) return ErrorButGoOn;
00969 
00970   while ( !msg->headerField( mParameter.latin1() ).isEmpty() )
00971     msg->removeHeaderField( mParameter.latin1() );
00972   return GoOn;
00973 }
00974 
00975 void KMFilterActionRemoveHeader::setParamWidgetValue( QWidget* paramWidget ) const
00976 {
00977   QComboBox * cb = dynamic_cast<QComboBox*>(paramWidget);
00978   Q_ASSERT( cb );
00979 
00980   int idx = mParameterList.findIndex( mParameter );
00981   cb->clear();
00982   cb->insertStringList( mParameterList );
00983   if ( idx < 0 ) {
00984     cb->insertItem( mParameter );
00985     cb->setCurrentItem( cb->count() - 1 );
00986   } else {
00987     cb->setCurrentItem( idx );
00988   }
00989 }
00990 
00991 
00992 //=============================================================================
00993 // KMFilterActionAddHeader - add header
00994 // Add a header with the given value.
00995 //=============================================================================
00996 class KMFilterActionAddHeader: public KMFilterActionWithStringList
00997 {
00998 public:
00999   KMFilterActionAddHeader();
01000   virtual ReturnCode process(KMMessage* msg) const;
01001   virtual QWidget* createParamWidget( QWidget* parent ) const;
01002   virtual void setParamWidgetValue( QWidget* paramWidget ) const;
01003   virtual void applyParamWidgetValue( QWidget* paramWidget );
01004   virtual void clearParamWidget( QWidget* paramWidget ) const;
01005 
01006   virtual const QString argsAsString() const;
01007   virtual void argsFromString( const QString argsStr );
01008 
01009   static KMFilterAction* newAction()
01010   {
01011     return (new KMFilterActionAddHeader);
01012   }
01013 private:
01014   QString mValue;
01015 };
01016 
01017 KMFilterActionAddHeader::KMFilterActionAddHeader()
01018   : KMFilterActionWithStringList( "add header", i18n("Add Header") )
01019 {
01020   mParameterList << ""
01021                  << "Reply-To"
01022                  << "Delivered-To"
01023                  << "X-KDE-PR-Message"
01024                  << "X-KDE-PR-Package"
01025                  << "X-KDE-PR-Keywords";
01026   mParameter = *mParameterList.at(0);
01027 }
01028 
01029 KMFilterAction::ReturnCode KMFilterActionAddHeader::process(KMMessage* msg) const
01030 {
01031   if ( mParameter.isEmpty() ) return ErrorButGoOn;
01032 
01033   msg->setHeaderField( mParameter.latin1(), mValue );
01034   return GoOn;
01035 }
01036 
01037 QWidget* KMFilterActionAddHeader::createParamWidget( QWidget* parent ) const
01038 {
01039   QWidget *w = new QWidget( parent );
01040   QHBoxLayout *hbl = new QHBoxLayout( w );
01041   hbl->setSpacing( 4 );
01042   QComboBox *cb = new QComboBox( TRUE, w, "combo" );
01043   cb->setInsertionPolicy( QComboBox::AtBottom );
01044   hbl->addWidget( cb, 0 /* stretch */ );
01045   QLabel *l = new QLabel( i18n("With value:"), w );
01046   l->setFixedWidth( l->sizeHint().width() );
01047   hbl->addWidget( l, 0 );
01048   QLineEdit *le = new KLineEdit( w, "ledit" );
01049   hbl->addWidget( le, 1 );
01050   setParamWidgetValue( w );
01051   return w;
01052 }
01053 
01054 void KMFilterActionAddHeader::setParamWidgetValue( QWidget* paramWidget ) const
01055 {
01056   int idx = mParameterList.findIndex( mParameter );
01057   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01058   Q_ASSERT( cb );
01059   cb->clear();
01060   cb->insertStringList( mParameterList );
01061   if ( idx < 0 ) {
01062     cb->insertItem( mParameter );
01063     cb->setCurrentItem( cb->count() - 1 );
01064   } else {
01065     cb->setCurrentItem( idx );
01066   }
01067   QLineEdit *le = (QLineEdit*)paramWidget->child("ledit");
01068   Q_ASSERT( le );
01069   le->setText( mValue );
01070 }
01071 
01072 void KMFilterActionAddHeader::applyParamWidgetValue( QWidget* paramWidget )
01073 {
01074   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01075   Q_ASSERT( cb );
01076   mParameter = cb->currentText();
01077 
01078   QLineEdit *le = (QLineEdit*)paramWidget->child("ledit");
01079   Q_ASSERT( le );
01080   mValue = le->text();
01081 }
01082 
01083 void KMFilterActionAddHeader::clearParamWidget( QWidget* paramWidget ) const
01084 {
01085   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01086   Q_ASSERT( cb );
01087   cb->setCurrentItem(0);
01088   QLineEdit *le = (QLineEdit*)paramWidget->child("ledit");
01089   Q_ASSERT( le );
01090   le->clear();
01091 }
01092 
01093 const QString KMFilterActionAddHeader::argsAsString() const
01094 {
01095   QString result = mParameter;
01096   result += '\t';
01097   result += mValue;
01098 
01099   return result;
01100 }
01101 
01102 void KMFilterActionAddHeader::argsFromString( const QString argsStr )
01103 {
01104   QStringList l = QStringList::split( '\t', argsStr, TRUE /*allow empty entries*/ );
01105   QString s;
01106   if ( l.count() < 2 ) {
01107     s = l[0];
01108     mValue = "";
01109   } else {
01110     s = l[0];
01111     mValue = l[1];
01112   }
01113 
01114   int idx = mParameterList.findIndex( s );
01115   if ( idx < 0 ) {
01116     mParameterList.append( s );
01117     idx = mParameterList.count() - 1;
01118   }
01119   mParameter = *mParameterList.at( idx );
01120 }
01121 
01122 
01123 //=============================================================================
01124 // KMFilterActionRewriteHeader - rewrite header
01125 // Rewrite a header using a regexp.
01126 //=============================================================================
01127 class KMFilterActionRewriteHeader: public KMFilterActionWithStringList
01128 {
01129 public:
01130   KMFilterActionRewriteHeader();
01131   virtual ReturnCode process(KMMessage* msg) const;
01132   virtual QWidget* createParamWidget( QWidget* parent ) const;
01133   virtual void setParamWidgetValue( QWidget* paramWidget ) const;
01134   virtual void applyParamWidgetValue( QWidget* paramWidget );
01135   virtual void clearParamWidget( QWidget* paramWidget ) const;
01136 
01137   virtual const QString argsAsString() const;
01138   virtual void argsFromString( const QString argsStr );
01139 
01140   static KMFilterAction* newAction()
01141   {
01142     return (new KMFilterActionRewriteHeader);
01143   }
01144 private:
01145   KRegExp3 mRegExp;
01146   QString mReplacementString;
01147 };
01148 
01149 KMFilterActionRewriteHeader::KMFilterActionRewriteHeader()
01150   : KMFilterActionWithStringList( "rewrite header", i18n("Rewrite Header") )
01151 {
01152   mParameterList << ""
01153                  << "Subject"
01154                  << "Reply-To"
01155                  << "Delivered-To"
01156                  << "X-KDE-PR-Message"
01157                  << "X-KDE-PR-Package"
01158                  << "X-KDE-PR-Keywords";
01159   mParameter = *mParameterList.at(0);
01160 }
01161 
01162 KMFilterAction::ReturnCode KMFilterActionRewriteHeader::process(KMMessage* msg) const
01163 {
01164   if ( mParameter.isEmpty() || !mRegExp.isValid() )
01165     return ErrorButGoOn;
01166 
01167   KRegExp3 rx = mRegExp; // KRegExp3::replace is not const.
01168 
01169   QString newValue = rx.replace( msg->headerField( mParameter.latin1() ),
01170                                      mReplacementString );
01171 
01172   msg->setHeaderField( mParameter.latin1(), newValue );
01173   return GoOn;
01174 }
01175 
01176 QWidget* KMFilterActionRewriteHeader::createParamWidget( QWidget* parent ) const
01177 {
01178   QWidget *w = new QWidget( parent );
01179   QHBoxLayout *hbl = new QHBoxLayout( w );
01180   hbl->setSpacing( 4 );
01181 
01182   QComboBox *cb = new QComboBox( TRUE, w, "combo" );
01183   cb->setInsertionPolicy( QComboBox::AtBottom );
01184   hbl->addWidget( cb, 0 /* stretch */ );
01185 
01186   QLabel *l = new QLabel( i18n("Replace:"), w );
01187   l->setFixedWidth( l->sizeHint().width() );
01188   hbl->addWidget( l, 0 );
01189 
01190   QLineEdit *le = new KLineEdit( w, "search" );
01191   hbl->addWidget( le, 1 );
01192 
01193   l = new QLabel( i18n("With:"), w );
01194   l->setFixedWidth( l->sizeHint().width() );
01195   hbl->addWidget( l, 0 );
01196 
01197   le = new KLineEdit( w, "replace" );
01198   hbl->addWidget( le, 1 );
01199 
01200   setParamWidgetValue( w );
01201   return w;
01202 }
01203 
01204 void KMFilterActionRewriteHeader::setParamWidgetValue( QWidget* paramWidget ) const
01205 {
01206   int idx = mParameterList.findIndex( mParameter );
01207   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01208   Q_ASSERT( cb );
01209 
01210   cb->clear();
01211   cb->insertStringList( mParameterList );
01212   if ( idx < 0 ) {
01213     cb->insertItem( mParameter );
01214     cb->setCurrentItem( cb->count() - 1 );
01215   } else {
01216     cb->setCurrentItem( idx );
01217   }
01218 
01219   QLineEdit *le = (QLineEdit*)paramWidget->child("search");
01220   Q_ASSERT( le );
01221   le->setText( mRegExp.pattern() );
01222 
01223   le = (QLineEdit*)paramWidget->child("replace");
01224   Q_ASSERT( le );
01225   le->setText( mReplacementString );
01226 }
01227 
01228 void KMFilterActionRewriteHeader::applyParamWidgetValue( QWidget* paramWidget )
01229 {
01230   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01231   Q_ASSERT( cb );
01232   mParameter = cb->currentText();
01233 
01234   QLineEdit *le = (QLineEdit*)paramWidget->child("search");
01235   Q_ASSERT( le );
01236   mRegExp.setPattern( le->text() );
01237 
01238   le = (QLineEdit*)paramWidget->child("replace");
01239   Q_ASSERT( le );
01240   mReplacementString = le->text();
01241 }
01242 
01243 void KMFilterActionRewriteHeader::clearParamWidget( QWidget* paramWidget ) const
01244 {
01245   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01246   Q_ASSERT( cb );
01247   cb->setCurrentItem(0);
01248 
01249   QLineEdit *le = (QLineEdit*)paramWidget->child("search");
01250   Q_ASSERT( le );
01251   le->clear();
01252 
01253   le = (QLineEdit*)paramWidget->child("replace");
01254   Q_ASSERT( le );
01255   le->clear();
01256 }
01257 
01258 const QString KMFilterActionRewriteHeader::argsAsString() const
01259 {
01260   QString result = mParameter;
01261   result += '\t';
01262   result += mRegExp.pattern();
01263   result += '\t';
01264   result += mReplacementString;
01265 
01266   return result;
01267 }
01268 
01269 void KMFilterActionRewriteHeader::argsFromString( const QString argsStr )
01270 {
01271   QStringList l = QStringList::split( '\t', argsStr, TRUE /*allow empty entries*/ );
01272   QString s;
01273 
01274   s = l[0];
01275   mRegExp.setPattern( l[1] );
01276   mReplacementString = l[2];
01277 
01278   int idx = mParameterList.findIndex( s );
01279   if ( idx < 0 ) {
01280     mParameterList.append( s );
01281     idx = mParameterList.count() - 1;
01282   }
01283   mParameter = *mParameterList.at( idx );
01284 }
01285 
01286 
01287 //=============================================================================
01288 // KMFilterActionMove - file into folder
01289 // File message into another mail folder
01290 //=============================================================================
01291 class KMFilterActionMove: public KMFilterActionWithFolder
01292 {
01293 public:
01294   KMFilterActionMove();
01295   virtual ReturnCode process(KMMessage* msg) const;
01296   virtual bool requiresBody(KMMsgBase*) const;
01297   static KMFilterAction* newAction(void);
01298 };
01299 
01300 KMFilterAction* KMFilterActionMove::newAction(void)
01301 {
01302   return (new KMFilterActionMove);
01303 }
01304 
01305 KMFilterActionMove::KMFilterActionMove()
01306   : KMFilterActionWithFolder( "transfer", i18n("File into Folder") )
01307 {
01308 }
01309 
01310 KMFilterAction::ReturnCode KMFilterActionMove::process(KMMessage* msg) const
01311 {
01312   if ( !mFolder )
01313     return ErrorButGoOn;
01314 
01315   MessageProperty::setFilterFolder( msg, mFolder );
01316   return GoOn;
01317 }
01318 
01319 bool KMFilterActionMove::requiresBody(KMMsgBase*) const
01320 {
01321     return false; //iff mFolder->folderMgr == msgBase->parent()->folderMgr;
01322 }
01323 
01324 
01325 //=============================================================================
01326 // KMFilterActionCopy - copy into folder
01327 // Copy message into another mail folder
01328 //=============================================================================
01329 class KMFilterActionCopy: public KMFilterActionWithFolder
01330 {
01331 public:
01332   KMFilterActionCopy();
01333   virtual ReturnCode process(KMMessage* msg) const;
01334   virtual void processAsync(KMMessage* msg) const;
01335   virtual bool requiresBody(KMMsgBase*) const;
01336   static KMFilterAction* newAction(void);
01337 };
01338 
01339 KMFilterAction* KMFilterActionCopy::newAction(void)
01340 {
01341   return (new KMFilterActionCopy);
01342 }
01343 
01344 KMFilterActionCopy::KMFilterActionCopy()
01345   : KMFilterActionWithFolder( "copy", i18n("Copy Into Folder") )
01346 {
01347 }
01348 
01349 KMFilterAction::ReturnCode KMFilterActionCopy::process(KMMessage* msg) const
01350 {
01351   // TODO opening and closing the folder is a trade off.
01352   // Perhaps Copy is a seldomly used action for now,
01353   // but I gonna look at improvements ASAP.
01354   if ( !mFolder && mFolder->open() != 0 )
01355     return ErrorButGoOn;
01356 
01357   // copy the message 1:1
01358   KMMessage* msgCopy = new KMMessage;
01359   msgCopy->fromDwString(msg->asDwString());
01360 
01361   int index;
01362   int rc = mFolder->addMsg(msgCopy, &index);
01363   if (rc == 0 && index != -1)
01364     mFolder->unGetMsg( index );
01365   mFolder->close();
01366 
01367   return GoOn;
01368 }
01369 
01370 void KMFilterActionCopy::processAsync(KMMessage* msg) const
01371 {
01372   // FIXME remove the debug output
01373   kdDebug(5006) << "##### KMFilterActionCopy::processAsync(KMMessage* msg)" << endl;
01374   ActionScheduler *handler = MessageProperty::filterHandler( msg );
01375 
01376   KMCommand *cmd = new KMCopyCommand( mFolder, msg );
01377   QObject::connect( cmd, SIGNAL( completed( KMCommand * ) ),
01378                     handler, SLOT( copyMessageFinished( KMCommand * ) ) );
01379   cmd->start();
01380 }
01381 
01382 bool KMFilterActionCopy::requiresBody(KMMsgBase*) const
01383 {
01384     return true;
01385 }
01386 
01387 
01388 //=============================================================================
01389 // KMFilterActionForward - forward to
01390 // Forward message to another user
01391 //=============================================================================
01392 class KMFilterActionForward: public KMFilterActionWithAddress
01393 {
01394 public:
01395   KMFilterActionForward();
01396   virtual ReturnCode process(KMMessage* msg) const;
01397   static KMFilterAction* newAction(void);
01398 };
01399 
01400 KMFilterAction* KMFilterActionForward::newAction(void)
01401 {
01402   return (new KMFilterActionForward);
01403 }
01404 
01405 KMFilterActionForward::KMFilterActionForward()
01406   : KMFilterActionWithAddress( "forward", i18n("Forward To") )
01407 {
01408 }
01409 
01410 KMFilterAction::ReturnCode KMFilterActionForward::process(KMMessage* aMsg) const
01411 {
01412   if ( mParameter.isEmpty() )
01413     return ErrorButGoOn;
01414 
01415   // avoid endless loops when this action is used in a filter
01416   // which applies to sent messages
01417   if ( KMMessage::addressIsInAddressList( mParameter, aMsg->to() ) )
01418     return ErrorButGoOn;
01419 
01420   // Create the forwarded message by hand to make forwarding of messages with
01421   // attachments work.
01422   // Note: This duplicates a lot of code from KMMessage::createForward() and
01423   //       KMComposeWin::applyChanges().
01424   // ### FIXME: Remove the code duplication again.
01425 
01426   KMMessage* msg = new KMMessage;
01427 
01428   msg->initFromMessage( aMsg );
01429 
01430   QString st = QString::fromUtf8( aMsg->createForwardBody() );
01431   QCString
01432     encoding = KMMsgBase::autoDetectCharset( aMsg->charset(),
01433                                              KMMessage::preferredCharsets(),
01434                                              st );
01435   if( encoding.isEmpty() )
01436     encoding = "utf-8";
01437   QCString str = KMMsgBase::codecForName( encoding )->fromUnicode( st );
01438 
01439   msg->setCharset( encoding );
01440   msg->setTo( mParameter );
01441   msg->setSubject( "Fwd: " + aMsg->subject() );
01442 
01443   bool isQP = kmkernel->msgSender()->sendQuotedPrintable();
01444 
01445   if( aMsg->numBodyParts() == 0 )
01446   {
01447     msg->setAutomaticFields( true );
01448     msg->setHeaderField( "Content-Type", "text/plain" );
01449     // msg->setCteStr( isQP ? "quoted-printable": "8bit" );
01450     QValueList<int> dummy;
01451     msg->setBodyAndGuessCte(str, dummy, !isQP);
01452     msg->setCharset( encoding );
01453     if( isQP )
01454       msg->setBodyEncoded( str );
01455     else
01456       msg->setBody( str );
01457   }
01458   else
01459   {
01460     KMMessagePart bodyPart, msgPart;
01461 
01462     msg->removeHeaderField( "Content-Type" );
01463     msg->removeHeaderField( "Content-Transfer-Encoding" );
01464     msg->setAutomaticFields( true );
01465     msg->setBody( "This message is in MIME format.\n\n" );
01466 
01467     bodyPart.setTypeStr( "text" );
01468     bodyPart.setSubtypeStr( "plain" );
01469     // bodyPart.setCteStr( isQP ? "quoted-printable": "8bit" );
01470     QValueList<int> dummy;
01471     bodyPart.setBodyAndGuessCte(str, dummy, !isQP);
01472     bodyPart.setCharset( encoding );
01473     bodyPart.setBodyEncoded( str );
01474     msg->addBodyPart( &bodyPart );
01475 
01476     for( int i = 0; i < aMsg->numBodyParts(); i++ )
01477     {
01478       aMsg->bodyPart( i, &msgPart );
01479       if( i > 0 || qstricmp( msgPart.typeStr(), "text" ) != 0 )
01480         msg->addBodyPart( &msgPart );
01481     }
01482   }
01483   msg->cleanupHeader();
01484   msg->link( aMsg, KMMsgStatusForwarded );
01485 
01486   sendMDN( aMsg, KMime::MDN::Dispatched );
01487 
01488   if ( !kmkernel->msgSender()->send( msg, FALSE ) ) {
01489     kdDebug(5006) << "KMFilterAction: could not forward message (sending failed)" << endl;
01490     return ErrorButGoOn; // error: couldn't send
01491   }
01492   return GoOn;
01493 }
01494 
01495 
01496 //=============================================================================
01497 // KMFilterActionRedirect - redirect to
01498 // Redirect message to another user
01499 //=============================================================================
01500 class KMFilterActionRedirect: public KMFilterActionWithAddress
01501 {
01502 public:
01503   KMFilterActionRedirect();
01504   virtual ReturnCode process(KMMessage* msg) const;
01505   static KMFilterAction* newAction(void);
01506 };
01507 
01508 KMFilterAction* KMFilterActionRedirect::newAction(void)
01509 {
01510   return (new KMFilterActionRedirect);
01511 }
01512 
01513 KMFilterActionRedirect::KMFilterActionRedirect()
01514   : KMFilterActionWithAddress( "redirect", i18n("Redirect To") )
01515 {
01516 }
01517 
01518 KMFilterAction::ReturnCode KMFilterActionRedirect::process(KMMessage* aMsg) const
01519 {
01520   KMMessage* msg;
01521   if ( mParameter.isEmpty() )
01522     return ErrorButGoOn;
01523 
01524   msg = aMsg->createRedirect2( mParameter );
01525 
01526   sendMDN( aMsg, KMime::MDN::Dispatched );
01527 
01528   if ( !kmkernel->msgSender()->send( msg, FALSE ) ) {
01529     kdDebug(5006) << "KMFilterAction: could not redirect message (sending failed)" << endl;
01530     return ErrorButGoOn; // error: couldn't send
01531   }
01532   return GoOn;
01533 }
01534 
01535 
01536 //=============================================================================
01537 // KMFilterActionExec - execute command
01538 // Execute a shell command
01539 //=============================================================================
01540 class KMFilterActionExec : public KMFilterActionWithCommand
01541 {
01542 public:
01543   KMFilterActionExec();
01544   virtual ReturnCode process(KMMessage* msg) const;
01545   static KMFilterAction* newAction(void);
01546 };
01547 
01548 KMFilterAction* KMFilterActionExec::newAction(void)
01549 {
01550   return (new KMFilterActionExec());
01551 }
01552 
01553 KMFilterActionExec::KMFilterActionExec()
01554   : KMFilterActionWithCommand( "execute", i18n("Execute Command") )
01555 {
01556 }
01557 
01558 KMFilterAction::ReturnCode KMFilterActionExec::process(KMMessage *aMsg) const
01559 {
01560   return KMFilterActionWithCommand::genericProcess( aMsg, false ); // ignore output
01561 }
01562 
01563 //=============================================================================
01564 // KMFilterActionExtFilter - use external filter app
01565 // External message filter: executes a shell command with message
01566 // on stdin; altered message is expected on stdout.
01567 //=============================================================================
01568 
01569 #include <weaver.h>
01570 class PipeJob : public KPIM::ThreadWeaver::Job
01571 {
01572   public:
01573     PipeJob(QObject* parent = 0 , const char* name = 0, KMMessage* aMsg = 0, QString cmd = 0, QString tempFileName = 0 )
01574       : Job (parent, name),
01575         mTempFileName(tempFileName),
01576         mCmd(cmd),
01577         mMsg( aMsg )
01578     {
01579     }
01580 
01581     ~PipeJob() {}
01582     virtual void processEvent( KPIM::ThreadWeaver::Event *ev )
01583     {
01584       KPIM::ThreadWeaver::Job::processEvent( ev );
01585       if ( ev->action() == KPIM::ThreadWeaver::Event::JobFinished )
01586         deleteLater( );
01587     }
01588   protected:
01589     void run()
01590     {
01591       KPIM::ThreadWeaver::debug (1, "PipeJob::run: doing it .\n");
01592       FILE *p;
01593       QByteArray ba;
01594 
01595       p = popen(QFile::encodeName(mCmd), "r");
01596       int len =100;
01597       char buffer[100];
01598       // append data to ba:
01599       while (true)  {
01600         if (! fgets( buffer, len, p ) ) break;
01601         int oldsize = ba.size();
01602         ba.resize( oldsize + strlen(buffer) );
01603         qmemmove( ba.begin() + oldsize, buffer, strlen(buffer) );
01604       }
01605       pclose(p);
01606       if ( !ba.isEmpty() ) {
01607         KPIM::ThreadWeaver::debug (1, "PipeJob::run: %s", QString(ba).latin1() );
01608         mMsg->fromByteArray( ba );
01609       }
01610 
01611       KPIM::ThreadWeaver::debug (1, "PipeJob::run: done.\n" );
01612       // unlink the tempFile
01613       QFile::remove(mTempFileName);
01614     }
01615     QString mTempFileName;
01616     QString mCmd;
01617     KMMessage *mMsg;
01618 };
01619 
01620 class KMFilterActionExtFilter: public KMFilterActionWithCommand
01621 {
01622 public:
01623   KMFilterActionExtFilter();
01624   virtual ReturnCode process(KMMessage* msg) const;
01625   virtual void processAsync(KMMessage* msg) const;
01626   static KMFilterAction* newAction(void);
01627 };
01628 
01629 KMFilterAction* KMFilterActionExtFilter::newAction(void)
01630 {
01631   return (new KMFilterActionExtFilter);
01632 }
01633 
01634 KMFilterActionExtFilter::KMFilterActionExtFilter()
01635   : KMFilterActionWithCommand( "filter app", i18n("Pipe Through") )
01636 {
01637 }
01638 KMFilterAction::ReturnCode KMFilterActionExtFilter::process(KMMessage* aMsg) const
01639 {
01640   return KMFilterActionWithCommand::genericProcess( aMsg, true ); // use output
01641 }
01642 
01643 void KMFilterActionExtFilter::processAsync(KMMessage* aMsg) const
01644 {
01645 
01646   ActionScheduler *handler = MessageProperty::filterHandler( aMsg->getMsgSerNum() );
01647   KTempFile * inFile = new KTempFile;
01648   inFile->setAutoDelete(FALSE);
01649 
01650   QPtrList<KTempFile> atmList;
01651   atmList.setAutoDelete(TRUE);
01652   atmList.append( inFile );
01653 
01654   QString commandLine = substituteCommandLineArgsFor( aMsg , atmList );
01655   if ( commandLine.isEmpty() )
01656     handler->actionMessage( ErrorButGoOn );
01657 
01658   // The parentheses force the creation of a subshell
01659   // in which the user-specified command is executed.
01660   // This is to really catch all output of the command as well
01661   // as to avoid clashes of our redirection with the ones
01662   // the user may have specified. In the long run, we
01663   // shouldn't be using tempfiles at all for this class, due
01664   // to security aspects. (mmutz)
01665   commandLine =  "(" + commandLine + ") <" + inFile->name();
01666 
01667   // write message to file
01668   QString tempFileName = inFile->name();
01669   KPIM::kCStringToFile( aMsg->asString(), tempFileName, //###
01670       false, false, false );
01671   inFile->close();
01672 
01673   PipeJob *job = new PipeJob(0, 0, aMsg, commandLine, tempFileName);
01674   QObject::connect ( job, SIGNAL( done() ), handler, SLOT( actionMessage() ) );
01675   kmkernel->weaver()->enqueue(job);
01676 }
01677 
01678 //=============================================================================
01679 // KMFilterActionExecSound - execute command
01680 // Execute a sound
01681 //=============================================================================
01682 class KMFilterActionExecSound : public KMFilterActionWithTest
01683 {
01684 public:
01685   KMFilterActionExecSound();
01686   virtual ReturnCode process(KMMessage* msg) const;
01687   virtual bool requiresBody(KMMsgBase*) const;
01688   static KMFilterAction* newAction(void);
01689 };
01690 
01691 KMFilterActionWithTest::KMFilterActionWithTest( const char* aName, const QString aLabel )
01692   : KMFilterAction( aName, aLabel )
01693 {
01694 }
01695 
01696 KMFilterActionWithTest::~KMFilterActionWithTest()
01697 {
01698 }
01699 
01700 QWidget* KMFilterActionWithTest::createParamWidget( QWidget* parent ) const
01701 {
01702   KMSoundTestWidget *le = new KMSoundTestWidget(parent);
01703   le->setUrl( mParameter );
01704   return le;
01705 }
01706 
01707 
01708 void KMFilterActionWithTest::applyParamWidgetValue( QWidget* paramWidget )
01709 {
01710   mParameter = ((KMSoundTestWidget*)paramWidget)->url();
01711 }
01712 
01713 void KMFilterActionWithTest::setParamWidgetValue( QWidget* paramWidget ) const
01714 {
01715   ((KMSoundTestWidget*)paramWidget)->setUrl( mParameter );
01716 }
01717 
01718 void KMFilterActionWithTest::clearParamWidget( QWidget* paramWidget ) const
01719 {
01720   ((KMSoundTestWidget*)paramWidget)->clear();
01721 }
01722 
01723 void KMFilterActionWithTest::argsFromString( const QString argsStr )
01724 {
01725   mParameter = argsStr;
01726 }
01727 
01728 const QString KMFilterActionWithTest::argsAsString() const
01729 {
01730   return mParameter;
01731 }
01732 
01733 
01734 KMFilterActionExecSound::KMFilterActionExecSound()
01735   : KMFilterActionWithTest( "play sound", i18n("Play Sound") )
01736 {
01737 }
01738 
01739 KMFilterAction* KMFilterActionExecSound::newAction(void)
01740 {
01741   return (new KMFilterActionExecSound());
01742 }
01743 
01744 KMFilterAction::ReturnCode KMFilterActionExecSound::process(KMMessage*) const
01745 {
01746   if ( mParameter.isEmpty() )
01747     return ErrorButGoOn;
01748   QString play = mParameter;
01749   QString file = QString::fromLatin1("file:");
01750   if (mParameter.startsWith(file))
01751     play = mParameter.mid(file.length());
01752   KAudioPlayer::play(QFile::encodeName(play));
01753   return GoOn;
01754 }
01755 
01756 bool KMFilterActionExecSound::requiresBody(KMMsgBase*) const
01757 {
01758   return false;
01759 }
01760 
01761 KMFilterActionWithUrl::KMFilterActionWithUrl( const char* aName, const QString aLabel )
01762   : KMFilterAction( aName, aLabel )
01763 {
01764 }
01765 
01766 KMFilterActionWithUrl::~KMFilterActionWithUrl()
01767 {
01768 }
01769 
01770 QWidget* KMFilterActionWithUrl::createParamWidget( QWidget* parent ) const
01771 {
01772   KURLRequester *le = new KURLRequester(parent);
01773   le->setURL( mParameter );
01774   return le;
01775 }
01776 
01777 
01778 void KMFilterActionWithUrl::applyParamWidgetValue( QWidget* paramWidget )
01779 {
01780   mParameter = ((KURLRequester*)paramWidget)->url();
01781 }
01782 
01783 void KMFilterActionWithUrl::setParamWidgetValue( QWidget* paramWidget ) const
01784 {
01785   ((KURLRequester*)paramWidget)->setURL( mParameter );
01786 }
01787 
01788 void KMFilterActionWithUrl::clearParamWidget( QWidget* paramWidget ) const
01789 {
01790   ((KURLRequester*)paramWidget)->clear();
01791 }
01792 
01793 void KMFilterActionWithUrl::argsFromString( const QString argsStr )
01794 {
01795   mParameter = argsStr;
01796 }
01797 
01798 const QString KMFilterActionWithUrl::argsAsString() const
01799 {
01800   return mParameter;
01801 }
01802 
01803 
01804 //=============================================================================
01805 //
01806 //   Filter  Action  Dictionary
01807 //
01808 //=============================================================================
01809 void KMFilterActionDict::init(void)
01810 {
01811   insert( KMFilterActionMove::newAction );
01812   insert( KMFilterActionCopy::newAction );
01813   insert( KMFilterActionIdentity::newAction );
01814   insert( KMFilterActionSetStatus::newAction );
01815   insert( KMFilterActionFakeDisposition::newAction );
01816   insert( KMFilterActionTransport::newAction );
01817   insert( KMFilterActionReplyTo::newAction );
01818   insert( KMFilterActionForward::newAction );
01819   insert( KMFilterActionRedirect::newAction );
01820   insert( KMFilterActionBounce::newAction );
01821   insert( KMFilterActionSendReceipt::newAction );
01822   insert( KMFilterActionExec::newAction );
01823   insert( KMFilterActionExtFilter::newAction );
01824   insert( KMFilterActionRemoveHeader::newAction );
01825   insert( KMFilterActionAddHeader::newAction );
01826   insert( KMFilterActionRewriteHeader::newAction );
01827   insert( KMFilterActionExecSound::newAction );
01828   // Register custom filter actions below this line.
01829 }
01830 // The int in the QDict constructor (23) must be a prime
01831 // and should be greater than the double number of KMFilterAction types
01832 KMFilterActionDict::KMFilterActionDict()
01833   : QDict<KMFilterActionDesc>(23)
01834 {
01835   mList.setAutoDelete(TRUE);
01836   init();
01837 }
01838 
01839 void KMFilterActionDict::insert( KMFilterActionNewFunc aNewFunc )
01840 {
01841   KMFilterAction *action = aNewFunc();
01842   KMFilterActionDesc* desc = new KMFilterActionDesc;
01843   desc->name = action->name();
01844   desc->label = action->label();
01845   desc->create = aNewFunc;
01846   QDict<KMFilterActionDesc>::insert( desc->name, desc );
01847   QDict<KMFilterActionDesc>::insert( desc->label, desc );
01848   mList.append( desc );
01849   delete action;
01850 }
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Aug 2 09:55:11 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003