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