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