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     // eat the output to avoid acummulation for following processes
00502     if ( withOutput ) 
00503       kmkernel->getCollectedStdOut( &shProc );
00504     return ErrorButGoOn;
00505   }
00506 
00507   if ( withOutput ) {
00508     // read altered message:
00509     QByteArray msgText = kmkernel->getCollectedStdOut( &shProc );
00510 
00511     if ( !msgText.isEmpty() ) {
00512     /* If the pipe through alters the message, it could very well 
00513        happen that it no longer has a X-UID header afterwards. That is
00514        unfortunate, as we need to removed the original from the folder
00515        using that, and look it up in the message. When the (new) message
00516        is uploaded, the header is stripped anyhow. */
00517       QString uid = aMsg->headerField("X-UID");
00518       aMsg->fromByteArray( msgText );
00519       aMsg->setHeaderField("X-UID",uid);
00520     }
00521     else
00522       return ErrorButGoOn;
00523   }
00524   return GoOn;
00525 }
00526 
00527 
00528 //=============================================================================
00529 //
00530 //   Specific  Filter  Actions
00531 //
00532 //=============================================================================
00533 
00534 //=============================================================================
00535 // KMFilterActionBounce - bounce
00536 // Return mail as undelivered.
00537 //=============================================================================
00538 class KMFilterActionBounce : public KMFilterActionWithNone
00539 {
00540 public:
00541   KMFilterActionBounce();
00542   virtual ReturnCode process(KMMessage* msg) const;
00543   static KMFilterAction* newAction(void);
00544 };
00545 
00546 KMFilterAction* KMFilterActionBounce::newAction(void)
00547 {
00548   return (new KMFilterActionBounce);
00549 }
00550 
00551 KMFilterActionBounce::KMFilterActionBounce()
00552   : KMFilterActionWithNone( "bounce", i18n("bounce") )
00553 {
00554 }
00555 
00556 KMFilterAction::ReturnCode KMFilterActionBounce::process(KMMessage* msg) const
00557 {
00558   KMMessage *bounceMsg = msg->createBounce( FALSE );
00559   if ( !bounceMsg ) return ErrorButGoOn;
00560 
00561   // Queue message. This is a) so that the user can check
00562   // the bounces before sending and b) for speed reasons.
00563   kmkernel->msgSender()->send( bounceMsg, FALSE );
00564 
00565   return GoOn;
00566 }
00567 
00568 
00569 //=============================================================================
00570 // KMFilterActionSendReceipt - send receipt
00571 // Return delivery receipt.
00572 //=============================================================================
00573 class KMFilterActionSendReceipt : public KMFilterActionWithNone
00574 {
00575 public:
00576   KMFilterActionSendReceipt();
00577   virtual ReturnCode process(KMMessage* msg) const;
00578   static KMFilterAction* newAction(void);
00579 };
00580 
00581 KMFilterAction* KMFilterActionSendReceipt::newAction(void)
00582 {
00583   return (new KMFilterActionSendReceipt);
00584 }
00585 
00586 KMFilterActionSendReceipt::KMFilterActionSendReceipt()
00587   : KMFilterActionWithNone( "confirm delivery", i18n("confirm delivery") )
00588 {
00589 }
00590 
00591 KMFilterAction::ReturnCode KMFilterActionSendReceipt::process(KMMessage* msg) const
00592 {
00593   KMMessage *receipt = msg->createDeliveryReceipt();
00594   if ( !receipt ) return ErrorButGoOn;
00595 
00596   // Queue message. This is a) so that the user can check
00597   // the receipt before sending and b) for speed reasons.
00598   kmkernel->msgSender()->send( receipt, FALSE );
00599 
00600   return GoOn;
00601 }
00602 
00603 
00604 
00605 //=============================================================================
00606 // KMFilterActionSetTransport - set transport to...
00607 // Specify mail transport (smtp server) to be used when replying to a message
00608 //=============================================================================
00609 class KMFilterActionTransport: public KMFilterActionWithString
00610 {
00611 public:
00612   KMFilterActionTransport();
00613   virtual ReturnCode process(KMMessage* msg) const;
00614   static KMFilterAction* newAction(void);
00615 };
00616 
00617 KMFilterAction* KMFilterActionTransport::newAction(void)
00618 {
00619   return (new KMFilterActionTransport);
00620 }
00621 
00622 KMFilterActionTransport::KMFilterActionTransport()
00623   : KMFilterActionWithString( "set transport", i18n("set transport to") )
00624 {
00625 }
00626 
00627 KMFilterAction::ReturnCode KMFilterActionTransport::process(KMMessage* msg) const
00628 {
00629   if ( mParameter.isEmpty() )
00630     return ErrorButGoOn;
00631   msg->setHeaderField( "X-KMail-Transport", mParameter );
00632   return GoOn;
00633 }
00634 
00635 
00636 //=============================================================================
00637 // KMFilterActionReplyTo - set Reply-To to
00638 // Set the Reply-to header in a message
00639 //=============================================================================
00640 class KMFilterActionReplyTo: public KMFilterActionWithString
00641 {
00642 public:
00643   KMFilterActionReplyTo();
00644   virtual ReturnCode process(KMMessage* msg) const;
00645   static KMFilterAction* newAction(void);
00646 };
00647 
00648 KMFilterAction* KMFilterActionReplyTo::newAction(void)
00649 {
00650   return (new KMFilterActionReplyTo);
00651 }
00652 
00653 KMFilterActionReplyTo::KMFilterActionReplyTo()
00654   : KMFilterActionWithString( "set Reply-To", i18n("set Reply-To to") )
00655 {
00656   mParameter = "";
00657 }
00658 
00659 KMFilterAction::ReturnCode KMFilterActionReplyTo::process(KMMessage* msg) const
00660 {
00661   msg->setHeaderField( "Reply-To", mParameter );
00662   return GoOn;
00663 }
00664 
00665 
00666 
00667 //=============================================================================
00668 // KMFilterActionIdentity - set identity to
00669 // Specify Identity to be used when replying to a message
00670 //=============================================================================
00671 class KMFilterActionIdentity: public KMFilterActionWithUOID
00672 {
00673 public:
00674   KMFilterActionIdentity();
00675   virtual ReturnCode process(KMMessage* msg) const;
00676   static KMFilterAction* newAction();
00677 
00678   QWidget * createParamWidget( QWidget * parent ) const;
00679   void applyParamWidgetValue( QWidget * parent );
00680   void setParamWidgetValue( QWidget * parent ) const;
00681   void clearParamWidget( QWidget * param ) const;
00682 };
00683 
00684 KMFilterAction* KMFilterActionIdentity::newAction()
00685 {
00686   return (new KMFilterActionIdentity);
00687 }
00688 
00689 KMFilterActionIdentity::KMFilterActionIdentity()
00690   : KMFilterActionWithUOID( "set identity", i18n("set identity to") )
00691 {
00692   mParameter = kmkernel->identityManager()->defaultIdentity().uoid();
00693 }
00694 
00695 KMFilterAction::ReturnCode KMFilterActionIdentity::process(KMMessage* msg) const
00696 {
00697   msg->setHeaderField( "X-KMail-Identity", QString::number( mParameter ) );
00698   return GoOn;
00699 }
00700 
00701 QWidget * KMFilterActionIdentity::createParamWidget( QWidget * parent ) const
00702 {
00703   IdentityCombo * ic = new IdentityCombo( parent );
00704   ic->setCurrentIdentity( mParameter );
00705   return ic;
00706 }
00707 
00708 void KMFilterActionIdentity::applyParamWidgetValue( QWidget * paramWidget )
00709 {
00710   IdentityCombo * ic = dynamic_cast<IdentityCombo*>( paramWidget );
00711   assert( ic );
00712   mParameter = ic->currentIdentity();
00713 }
00714 
00715 void KMFilterActionIdentity::clearParamWidget( QWidget * paramWidget ) const
00716 {
00717   IdentityCombo * ic = dynamic_cast<IdentityCombo*>( paramWidget );
00718   assert( ic );
00719   ic->setCurrentItem( 0 );
00720   //ic->setCurrentIdentity( kmkernel->identityManager()->defaultIdentity() );
00721 }
00722 
00723 void KMFilterActionIdentity::setParamWidgetValue( QWidget * paramWidget ) const
00724 {
00725   IdentityCombo * ic = dynamic_cast<IdentityCombo*>( paramWidget );
00726   assert( ic );
00727   ic->setCurrentIdentity( mParameter );
00728 }
00729 
00730 //=============================================================================
00731 // KMFilterActionSetStatus - set status to
00732 // Set the status of messages
00733 //=============================================================================
00734 class KMFilterActionSetStatus: public KMFilterActionWithStringList
00735 {
00736 public:
00737   KMFilterActionSetStatus();
00738   virtual ReturnCode process(KMMessage* msg) const;
00739   virtual bool requiresBody(KMMsgBase*) const;
00740 
00741   static KMFilterAction* newAction();
00742 
00743   virtual bool isEmpty() const { return false; }
00744 
00745   virtual void argsFromString( const QString argsStr );
00746   virtual const QString argsAsString() const;
00747 };
00748 
00749 
00750 static const KMMsgStatus stati[] =
00751 {
00752   KMMsgStatusFlag,
00753   KMMsgStatusRead,
00754   KMMsgStatusUnread,
00755   KMMsgStatusReplied,
00756   KMMsgStatusForwarded,
00757   KMMsgStatusOld,
00758   KMMsgStatusNew,
00759   KMMsgStatusWatched,
00760   KMMsgStatusIgnored,
00761   KMMsgStatusSpam,
00762   KMMsgStatusHam
00763 };
00764 static const int StatiCount = sizeof( stati ) / sizeof( KMMsgStatus );
00765 
00766 KMFilterAction* KMFilterActionSetStatus::newAction()
00767 {
00768   return (new KMFilterActionSetStatus);
00769 }
00770 
00771 KMFilterActionSetStatus::KMFilterActionSetStatus()
00772   : KMFilterActionWithStringList( "set status", i18n("mark as") )
00773 {
00774   // if you change this list, also update
00775   // KMFilterActionSetStatus::stati above
00776   mParameterList.append( "" );
00777   mParameterList.append( i18n("msg status","Important") );
00778   mParameterList.append( i18n("msg status","Read") );
00779   mParameterList.append( i18n("msg status","Unread") );
00780   mParameterList.append( i18n("msg status","Replied") );
00781   mParameterList.append( i18n("msg status","Forwarded") );
00782   mParameterList.append( i18n("msg status","Old") );
00783   mParameterList.append( i18n("msg status","New") );
00784   mParameterList.append( i18n("msg status","Watched") );
00785   mParameterList.append( i18n("msg status","Ignored") );
00786   mParameterList.append( i18n("msg status","Spam") );
00787   mParameterList.append( i18n("msg status","Ham") );
00788 
00789   mParameter = *mParameterList.at(0);
00790 }
00791 
00792 KMFilterAction::ReturnCode KMFilterActionSetStatus::process(KMMessage* msg) const
00793 {
00794   int idx = mParameterList.findIndex( mParameter );
00795   if ( idx < 1 ) return ErrorButGoOn;
00796 
00797   KMMsgStatus status = stati[idx-1] ;
00798   msg->setStatus( status );
00799   return GoOn;
00800 }
00801 
00802 bool KMFilterActionSetStatus::requiresBody(KMMsgBase*) const
00803 {
00804   return false;
00805 }
00806 
00807 void KMFilterActionSetStatus::argsFromString( const QString argsStr )
00808 {
00809   if ( argsStr.length() == 1 ) {
00810     for ( int i = 0 ; i < StatiCount ; i++ )
00811       if ( KMMsgBase::statusToStr(stati[i])[0] == argsStr[0] ) {
00812     mParameter = *mParameterList.at(i+1);
00813     return;
00814       }
00815   }
00816   mParameter = *mParameterList.at(0);
00817 }
00818 
00819 const QString KMFilterActionSetStatus::argsAsString() const
00820 {
00821   int idx = mParameterList.findIndex( mParameter );
00822   if ( idx < 1 ) return QString::null;
00823 
00824   KMMsgStatus status = stati[idx-1];
00825   return KMMsgBase::statusToStr(status);
00826 }
00827 
00828 
00829 //=============================================================================
00830 // KMFilterActionFakeDisposition - send fake MDN
00831 // Sends a fake MDN or forces an ignore.
00832 //=============================================================================
00833 class KMFilterActionFakeDisposition: public KMFilterActionWithStringList
00834 {
00835 public:
00836   KMFilterActionFakeDisposition();
00837   virtual ReturnCode process(KMMessage* msg) const;
00838   static KMFilterAction* newAction() {
00839     return (new KMFilterActionFakeDisposition);
00840   }
00841 
00842   virtual bool isEmpty() const { return false; }
00843 
00844   virtual void argsFromString( const QString argsStr );
00845   virtual const QString argsAsString() const;
00846 };
00847 
00848 
00849 // if you change this list, also update
00850 // the count in argsFromString
00851 static const KMime::MDN::DispositionType mdns[] =
00852 {
00853   KMime::MDN::Displayed,
00854   KMime::MDN::Deleted,
00855   KMime::MDN::Dispatched,
00856   KMime::MDN::Processed,
00857   KMime::MDN::Denied,
00858   KMime::MDN::Failed,
00859 };
00860 static const int numMDNs = sizeof mdns / sizeof *mdns;
00861 
00862 
00863 KMFilterActionFakeDisposition::KMFilterActionFakeDisposition()
00864   : KMFilterActionWithStringList( "fake mdn", i18n("send fake MDN") )
00865 {
00866   // if you change this list, also update
00867   // mdns above
00868   mParameterList.append( "" );
00869   mParameterList.append( i18n("MDN type","Ignore") );
00870   mParameterList.append( i18n("MDN type","Displayed") );
00871   mParameterList.append( i18n("MDN type","Deleted") );
00872   mParameterList.append( i18n("MDN type","Dispatched") );
00873   mParameterList.append( i18n("MDN type","Processed") );
00874   mParameterList.append( i18n("MDN type","Denied") );
00875   mParameterList.append( i18n("MDN type","Failed") );
00876 
00877   mParameter = *mParameterList.at(0);
00878 }
00879 
00880 KMFilterAction::ReturnCode KMFilterActionFakeDisposition::process(KMMessage* msg) const
00881 {
00882   int idx = mParameterList.findIndex( mParameter );
00883   if ( idx < 1 ) return ErrorButGoOn;
00884 
00885   if ( idx == 1 ) // ignore
00886     msg->setMDNSentState( KMMsgMDNIgnore );
00887   else // send
00888     sendMDN( msg, mdns[idx-2] ); // skip first two entries: "" and "ignore"
00889   return GoOn;
00890 }
00891 
00892 void KMFilterActionFakeDisposition::argsFromString( const QString argsStr )
00893 {
00894   if ( argsStr.length() == 1 ) {
00895     if ( argsStr[0] == 'I' ) { // ignore
00896       mParameter = *mParameterList.at(1);
00897       return;
00898     }
00899     for ( int i = 0 ; i < numMDNs ; i++ )
00900       if ( char(mdns[i]) == argsStr[0] ) { // send
00901     mParameter = *mParameterList.at(i+2);
00902     return;
00903       }
00904   }
00905   mParameter = *mParameterList.at(0);
00906 }
00907 
00908 const QString KMFilterActionFakeDisposition::argsAsString() const
00909 {
00910   int idx = mParameterList.findIndex( mParameter );
00911   if ( idx < 1 ) return QString::null;
00912 
00913   return QString( QChar( idx < 2 ? 'I' : char(mdns[idx-2]) ) );
00914 }
00915 
00916 
00917 //=============================================================================
00918 // KMFilterActionRemoveHeader - remove header
00919 // Remove all instances of the given header field.
00920 //=============================================================================
00921 class KMFilterActionRemoveHeader: public KMFilterActionWithStringList
00922 {
00923 public:
00924   KMFilterActionRemoveHeader();
00925   virtual ReturnCode process(KMMessage* msg) const;
00926   virtual QWidget* createParamWidget( QWidget* parent ) const;
00927   virtual void setParamWidgetValue( QWidget* paramWidget ) const;
00928 
00929   static KMFilterAction* newAction();
00930 };
00931 
00932 KMFilterAction* KMFilterActionRemoveHeader::newAction()
00933 {
00934   return (new KMFilterActionRemoveHeader);
00935 }
00936 
00937 KMFilterActionRemoveHeader::KMFilterActionRemoveHeader()
00938   : KMFilterActionWithStringList( "remove header", i18n("remove header") )
00939 {
00940   mParameterList << ""
00941          << "Reply-To"
00942          << "Delivered-To"
00943          << "X-KDE-PR-Message"
00944          << "X-KDE-PR-Package"
00945          << "X-KDE-PR-Keywords";
00946   mParameter = *mParameterList.at(0);
00947 }
00948 
00949 QWidget* KMFilterActionRemoveHeader::createParamWidget( QWidget* parent ) const
00950 {
00951   QComboBox *cb = new QComboBox( TRUE/*editable*/, parent );
00952   cb->setInsertionPolicy( QComboBox::AtBottom );
00953   setParamWidgetValue( cb );
00954   return cb;
00955 }
00956 
00957 KMFilterAction::ReturnCode KMFilterActionRemoveHeader::process(KMMessage* msg) const
00958 {
00959   if ( mParameter.isEmpty() ) return ErrorButGoOn;
00960 
00961   while ( !msg->headerField( mParameter.latin1() ).isEmpty() )
00962     msg->removeHeaderField( mParameter.latin1() );
00963   return GoOn;
00964 }
00965 
00966 void KMFilterActionRemoveHeader::setParamWidgetValue( QWidget* paramWidget ) const
00967 {
00968   QComboBox * cb = dynamic_cast<QComboBox*>(paramWidget);
00969   Q_ASSERT( cb );
00970 
00971   int idx = mParameterList.findIndex( mParameter );
00972   cb->clear();
00973   cb->insertStringList( mParameterList );
00974   if ( idx < 0 ) {
00975     cb->insertItem( mParameter );
00976     cb->setCurrentItem( cb->count() - 1 );
00977   } else {
00978     cb->setCurrentItem( idx );
00979   }
00980 }
00981 
00982 
00983 //=============================================================================
00984 // KMFilterActionAddHeader - add header
00985 // Add a header with the given value.
00986 //=============================================================================
00987 class KMFilterActionAddHeader: public KMFilterActionWithStringList
00988 {
00989 public:
00990   KMFilterActionAddHeader();
00991   virtual ReturnCode process(KMMessage* msg) const;
00992   virtual QWidget* createParamWidget( QWidget* parent ) const;
00993   virtual void setParamWidgetValue( QWidget* paramWidget ) const;
00994   virtual void applyParamWidgetValue( QWidget* paramWidget );
00995   virtual void clearParamWidget( QWidget* paramWidget ) const;
00996 
00997   virtual const QString argsAsString() const;
00998   virtual void argsFromString( const QString argsStr );
00999 
01000   static KMFilterAction* newAction()
01001   {
01002     return (new KMFilterActionAddHeader);
01003   }
01004 private:
01005   QString mValue;
01006 };
01007 
01008 KMFilterActionAddHeader::KMFilterActionAddHeader()
01009   : KMFilterActionWithStringList( "add header", i18n("add header") )
01010 {
01011   mParameterList << ""
01012          << "Reply-To"
01013          << "Delivered-To"
01014          << "X-KDE-PR-Message"
01015          << "X-KDE-PR-Package"
01016          << "X-KDE-PR-Keywords";
01017   mParameter = *mParameterList.at(0);
01018 }
01019 
01020 KMFilterAction::ReturnCode KMFilterActionAddHeader::process(KMMessage* msg) const
01021 {
01022   if ( mParameter.isEmpty() ) return ErrorButGoOn;
01023 
01024   msg->setHeaderField( mParameter.latin1(), mValue );
01025   return GoOn;
01026 }
01027 
01028 QWidget* KMFilterActionAddHeader::createParamWidget( QWidget* parent ) const
01029 {
01030   QWidget *w = new QWidget( parent );
01031   QHBoxLayout *hbl = new QHBoxLayout( w );
01032   hbl->setSpacing( 4 );
01033   QComboBox *cb = new QComboBox( TRUE, w, "combo" );
01034   cb->setInsertionPolicy( QComboBox::AtBottom );
01035   hbl->addWidget( cb, 0 /* stretch */ );
01036   QLabel *l = new QLabel( i18n("with value"), w );
01037   l->setFixedWidth( l->sizeHint().width() );
01038   hbl->addWidget( l, 0 );
01039   QLineEdit *le = new KLineEdit( w, "ledit" );
01040   hbl->addWidget( le, 1 );
01041   setParamWidgetValue( w );
01042   return w;
01043 }
01044 
01045 void KMFilterActionAddHeader::setParamWidgetValue( QWidget* paramWidget ) const
01046 {
01047   int idx = mParameterList.findIndex( mParameter );
01048   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01049   Q_ASSERT( cb );
01050   cb->clear();
01051   cb->insertStringList( mParameterList );
01052   if ( idx < 0 ) {
01053     cb->insertItem( mParameter );
01054     cb->setCurrentItem( cb->count() - 1 );
01055   } else {
01056     cb->setCurrentItem( idx );
01057   }
01058   QLineEdit *le = (QLineEdit*)paramWidget->child("ledit");
01059   Q_ASSERT( le );
01060   le->setText( mValue );
01061 }
01062 
01063 void KMFilterActionAddHeader::applyParamWidgetValue( QWidget* paramWidget )
01064 {
01065   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01066   Q_ASSERT( cb );
01067   mParameter = cb->currentText();
01068 
01069   QLineEdit *le = (QLineEdit*)paramWidget->child("ledit");
01070   Q_ASSERT( le );
01071   mValue = le->text();
01072 }
01073 
01074 void KMFilterActionAddHeader::clearParamWidget( QWidget* paramWidget ) const
01075 {
01076   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01077   Q_ASSERT( cb );
01078   cb->setCurrentItem(0);
01079   QLineEdit *le = (QLineEdit*)paramWidget->child("ledit");
01080   Q_ASSERT( le );
01081   le->clear();
01082 }
01083 
01084 const QString KMFilterActionAddHeader::argsAsString() const
01085 {
01086   QString result = mParameter;
01087   result += '\t';
01088   result += mValue;
01089 
01090   return result;
01091 }
01092 
01093 void KMFilterActionAddHeader::argsFromString( const QString argsStr )
01094 {
01095   QStringList l = QStringList::split( '\t', argsStr, TRUE /*allow empty entries*/ );
01096   QString s;
01097   if ( l.count() < 2 ) {
01098     s = l[0];
01099     mValue = "";
01100   } else {
01101     s = l[0];
01102     mValue = l[1];
01103   }
01104 
01105   int idx = mParameterList.findIndex( s );
01106   if ( idx < 0 ) {
01107     mParameterList.append( s );
01108     idx = mParameterList.count() - 1;
01109   }
01110   mParameter = *mParameterList.at( idx );
01111 }
01112 
01113 
01114 //=============================================================================
01115 // KMFilterActionRewriteHeader - rewrite header
01116 // Rewrite a header using a regexp.
01117 //=============================================================================
01118 class KMFilterActionRewriteHeader: public KMFilterActionWithStringList
01119 {
01120 public:
01121   KMFilterActionRewriteHeader();
01122   virtual ReturnCode process(KMMessage* msg) const;
01123   virtual QWidget* createParamWidget( QWidget* parent ) const;
01124   virtual void setParamWidgetValue( QWidget* paramWidget ) const;
01125   virtual void applyParamWidgetValue( QWidget* paramWidget );
01126   virtual void clearParamWidget( QWidget* paramWidget ) const;
01127 
01128   virtual const QString argsAsString() const;
01129   virtual void argsFromString( const QString argsStr );
01130 
01131   static KMFilterAction* newAction()
01132   {
01133     return (new KMFilterActionRewriteHeader);
01134   }
01135 private:
01136   KRegExp3 mRegExp;
01137   QString mReplacementString;
01138 };
01139 
01140 KMFilterActionRewriteHeader::KMFilterActionRewriteHeader()
01141   : KMFilterActionWithStringList( "rewrite header", i18n("rewrite header") )
01142 {
01143   mParameterList << ""
01144          << "Subject"
01145          << "Reply-To"
01146          << "Delivered-To"
01147          << "X-KDE-PR-Message"
01148          << "X-KDE-PR-Package"
01149          << "X-KDE-PR-Keywords";
01150   mParameter = *mParameterList.at(0);
01151 }
01152 
01153 KMFilterAction::ReturnCode KMFilterActionRewriteHeader::process(KMMessage* msg) const
01154 {
01155   if ( mParameter.isEmpty() || !mRegExp.isValid() )
01156     return ErrorButGoOn;
01157 
01158   KRegExp3 rx = mRegExp; // KRegExp3::replace is not const.
01159 
01160   QString newValue = rx.replace( msg->headerField( mParameter.latin1() ),
01161                      mReplacementString );
01162 
01163   msg->setHeaderField( mParameter.latin1(), newValue );
01164   return GoOn;
01165 }
01166 
01167 QWidget* KMFilterActionRewriteHeader::createParamWidget( QWidget* parent ) const
01168 {
01169   QWidget *w = new QWidget( parent );
01170   QHBoxLayout *hbl = new QHBoxLayout( w );
01171   hbl->setSpacing( 4 );
01172 
01173   QComboBox *cb = new QComboBox( TRUE, w, "combo" );
01174   cb->setInsertionPolicy( QComboBox::AtBottom );
01175   hbl->addWidget( cb, 0 /* stretch */ );
01176 
01177   QLabel *l = new QLabel( i18n("replace"), w );
01178   l->setFixedWidth( l->sizeHint().width() );
01179   hbl->addWidget( l, 0 );
01180 
01181   QLineEdit *le = new KLineEdit( w, "search" );
01182   hbl->addWidget( le, 1 );
01183 
01184   l = new QLabel( i18n("with"), w );
01185   l->setFixedWidth( l->sizeHint().width() );
01186   hbl->addWidget( l, 0 );
01187 
01188   le = new KLineEdit( w, "replace" );
01189   hbl->addWidget( le, 1 );
01190 
01191   setParamWidgetValue( w );
01192   return w;
01193 }
01194 
01195 void KMFilterActionRewriteHeader::setParamWidgetValue( QWidget* paramWidget ) const
01196 {
01197   int idx = mParameterList.findIndex( mParameter );
01198   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01199   Q_ASSERT( cb );
01200 
01201   cb->clear();
01202   cb->insertStringList( mParameterList );
01203   if ( idx < 0 ) {
01204     cb->insertItem( mParameter );
01205     cb->setCurrentItem( cb->count() - 1 );
01206   } else {
01207     cb->setCurrentItem( idx );
01208   }
01209 
01210   QLineEdit *le = (QLineEdit*)paramWidget->child("search");
01211   Q_ASSERT( le );
01212   le->setText( mRegExp.pattern() );
01213 
01214   le = (QLineEdit*)paramWidget->child("replace");
01215   Q_ASSERT( le );
01216   le->setText( mReplacementString );
01217 }
01218 
01219 void KMFilterActionRewriteHeader::applyParamWidgetValue( QWidget* paramWidget )
01220 {
01221   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01222   Q_ASSERT( cb );
01223   mParameter = cb->currentText();
01224 
01225   QLineEdit *le = (QLineEdit*)paramWidget->child("search");
01226   Q_ASSERT( le );
01227   mRegExp.setPattern( le->text() );
01228 
01229   le = (QLineEdit*)paramWidget->child("replace");
01230   Q_ASSERT( le );
01231   mReplacementString = le->text();
01232 }
01233 
01234 void KMFilterActionRewriteHeader::clearParamWidget( QWidget* paramWidget ) const
01235 {
01236   QComboBox *cb = (QComboBox*)paramWidget->child("combo");
01237   Q_ASSERT( cb );
01238   cb->setCurrentItem(0);
01239 
01240   QLineEdit *le = (QLineEdit*)paramWidget->child("search");
01241   Q_ASSERT( le );
01242   le->clear();
01243 
01244   le = (QLineEdit*)paramWidget->child("replace");
01245   Q_ASSERT( le );
01246   le->clear();
01247 }
01248 
01249 const QString KMFilterActionRewriteHeader::argsAsString() const
01250 {
01251   QString result = mParameter;
01252   result += '\t';
01253   result += mRegExp.pattern();
01254   result += '\t';
01255   result += mReplacementString;
01256 
01257   return result;
01258 }
01259 
01260 void KMFilterActionRewriteHeader::argsFromString( const QString argsStr )
01261 {
01262   QStringList l = QStringList::split( '\t', argsStr, TRUE /*allow empty entries*/ );
01263   QString s;
01264 
01265   s = l[0];
01266   mRegExp.setPattern( l[1] );
01267   mReplacementString = l[2];
01268 
01269   int idx = mParameterList.findIndex( s );
01270   if ( idx < 0 ) {
01271     mParameterList.append( s );
01272     idx = mParameterList.count() - 1;
01273   }
01274   mParameter = *mParameterList.at( idx );
01275 }
01276 
01277 
01278 //=============================================================================
01279 // KMFilterActionMove - file into folder
01280 // File message into another mail folder
01281 //=============================================================================
01282 class KMFilterActionMove: public KMFilterActionWithFolder
01283 {
01284 public:
01285   KMFilterActionMove();
01286   virtual ReturnCode process(KMMessage* msg) const;
01287   virtual bool requiresBody(KMMsgBase*) const;
01288   static KMFilterAction* newAction(void);
01289 };
01290 
01291 KMFilterAction* KMFilterActionMove::newAction(void)
01292 {
01293   return (new KMFilterActionMove);
01294 }
01295 
01296 KMFilterActionMove::KMFilterActionMove()
01297   : KMFilterActionWithFolder( "transfer", i18n("file into folder") )
01298 {
01299 }
01300 
01301 KMFilterAction::ReturnCode KMFilterActionMove::process(KMMessage* msg) const
01302 {
01303   if ( !mFolder )
01304     return ErrorButGoOn;
01305 
01306   MessageProperty::setFilterFolder( msg, mFolder );
01307   return GoOn;
01308 }
01309 
01310 bool KMFilterActionMove::requiresBody(KMMsgBase*) const
01311 {
01312     return false; //iff mFolder->folderMgr == msgBase->parent()->folderMgr;
01313 }
01314 
01315 //=============================================================================
01316 // KMFilterActionForward - forward to
01317 // Forward message to another user
01318 //=============================================================================
01319 class KMFilterActionForward: public KMFilterActionWithAddress
01320 {
01321 public:
01322   KMFilterActionForward();
01323   virtual ReturnCode process(KMMessage* msg) const;
01324   static KMFilterAction* newAction(void);
01325 };
01326 
01327 KMFilterAction* KMFilterActionForward::newAction(void)
01328 {
01329   return (new KMFilterActionForward);
01330 }
01331 
01332 KMFilterActionForward::KMFilterActionForward()
01333   : KMFilterActionWithAddress( "forward", i18n("forward to") )
01334 {
01335 }
01336 
01337 KMFilterAction::ReturnCode KMFilterActionForward::process(KMMessage* aMsg) const
01338 {
01339   if ( mParameter.isEmpty() )
01340     return ErrorButGoOn;
01341 
01342   // Create the forwarded message by hand to make forwarding of messages with
01343   // attachments work.
01344   // Note: This duplicates a lot of code from KMMessage::createForward() and
01345   //       KMComposeWin::applyChanges().
01346   // ### FIXME: Remove the code duplication again.
01347 
01348   KMMessage* msg = new KMMessage;
01349 
01350   msg->initFromMessage( aMsg );
01351 
01352   QString st = QString::fromUtf8( aMsg->createForwardBody() );
01353   QCString
01354     encoding = KMMsgBase::autoDetectCharset( aMsg->charset(),
01355                                              KMMessage::preferredCharsets(),
01356                                              st );
01357   if( encoding.isEmpty() )
01358     encoding = "utf-8";
01359   QCString str = KMMsgBase::codecForName( encoding )->fromUnicode( st );
01360 
01361   msg->setCharset( encoding );
01362   msg->setTo( mParameter );
01363   msg->setSubject( "Fwd: " + aMsg->subject() );
01364 
01365   bool isQP = kmkernel->msgSender()->sendQuotedPrintable();
01366 
01367   if( aMsg->numBodyParts() == 0 )
01368   {
01369     msg->setAutomaticFields( true );
01370     msg->setHeaderField( "Content-Type", "text/plain" );
01371     // msg->setCteStr( isQP ? "quoted-printable": "8bit" );
01372     QValueList<int> dummy;
01373     msg->setBodyAndGuessCte(str, dummy, !isQP);
01374     msg->setCharset( encoding );
01375     if( isQP )
01376       msg->setBodyEncoded( str );
01377     else
01378       msg->setBody( str );
01379   }
01380   else
01381   {
01382     KMMessagePart bodyPart, msgPart;
01383 
01384     msg->removeHeaderField( "Content-Type" );
01385     msg->removeHeaderField( "Content-Transfer-Encoding" );
01386     msg->setAutomaticFields( true );
01387     msg->setBody( "This message is in MIME format.\n\n" );
01388 
01389     bodyPart.setTypeStr( "text" );
01390     bodyPart.setSubtypeStr( "plain" );
01391     // bodyPart.setCteStr( isQP ? "quoted-printable": "8bit" );
01392     QValueList<int> dummy;
01393     bodyPart.setBodyAndGuessCte(str, dummy, !isQP);
01394     bodyPart.setCharset( encoding );
01395     bodyPart.setBodyEncoded( str );
01396     msg->addBodyPart( &bodyPart );
01397 
01398     for( int i = 0; i < aMsg->numBodyParts(); i++ )
01399     {
01400       aMsg->bodyPart( i, &msgPart );
01401       if( i > 0 || qstricmp( msgPart.typeStr(), "text" ) != 0 )
01402         msg->addBodyPart( &msgPart );
01403     }
01404   }
01405   msg->cleanupHeader();
01406   msg->link( aMsg, KMMsgStatusForwarded );
01407 
01408   sendMDN( aMsg, KMime::MDN::Dispatched );
01409 
01410   if ( !kmkernel->msgSender()->send( msg, FALSE ) ) {
01411     kdDebug(5006) << "KMFilterAction: could not forward message (sending failed)" << endl;
01412     return ErrorButGoOn; // error: couldn't send
01413   }
01414   return GoOn;
01415 }
01416 
01417 
01418 //=============================================================================
01419 // KMFilterActionRedirect - redirect to
01420 // Redirect message to another user
01421 //=============================================================================
01422 class KMFilterActionRedirect: public KMFilterActionWithAddress
01423 {
01424 public:
01425   KMFilterActionRedirect();
01426   virtual ReturnCode process(KMMessage* msg) const;
01427   static KMFilterAction* newAction(void);
01428 };
01429 
01430 KMFilterAction* KMFilterActionRedirect::newAction(void)
01431 {
01432   return (new KMFilterActionRedirect);
01433 }
01434 
01435 KMFilterActionRedirect::KMFilterActionRedirect()
01436   : KMFilterActionWithAddress( "redirect", i18n("redirect to") )
01437 {
01438 }
01439 
01440 KMFilterAction::ReturnCode KMFilterActionRedirect::process(KMMessage* aMsg) const
01441 {
01442   KMMessage* msg;
01443   if ( mParameter.isEmpty() )
01444     return ErrorButGoOn;
01445 
01446   msg = aMsg->createRedirect();
01447   msg->setTo( mParameter );
01448 
01449   sendMDN( aMsg, KMime::MDN::Dispatched );
01450 
01451   if ( !kmkernel->msgSender()->send( msg, FALSE ) ) {
01452     kdDebug(5006) << "KMFilterAction: could not redirect message (sending failed)" << endl;
01453     return ErrorButGoOn; // error: couldn't send
01454   }
01455   return GoOn;
01456 }
01457 
01458 
01459 //=============================================================================
01460 // KMFilterActionExec - execute command
01461 // Execute a shell command
01462 //=============================================================================
01463 class KMFilterActionExec : public KMFilterActionWithCommand
01464 {
01465 public:
01466   KMFilterActionExec();
01467   virtual ReturnCode process(KMMessage* msg) const;
01468   static KMFilterAction* newAction(void);
01469 };
01470 
01471 KMFilterAction* KMFilterActionExec::newAction(void)
01472 {
01473   return (new KMFilterActionExec());
01474 }
01475 
01476 KMFilterActionExec::KMFilterActionExec()
01477   : KMFilterActionWithCommand( "execute", i18n("execute command") )
01478 {
01479 }
01480 
01481 KMFilterAction::ReturnCode KMFilterActionExec::process(KMMessage *aMsg) const
01482 {
01483   return KMFilterActionWithCommand::genericProcess( aMsg, false ); // ignore output
01484 }
01485 
01486 //=============================================================================
01487 // KMFilterActionExtFilter - use external filter app
01488 // External message filter: executes a shell command with message
01489 // on stdin; altered message is expected on stdout.
01490 //=============================================================================
01491 
01492 #include <weaver.h>
01493 class PipeJob : public KPIM::ThreadWeaver::Job
01494 {
01495   public:
01496     PipeJob(QObject* parent = 0 , const char* name = 0, KMMessage* aMsg = 0, QString cmd = 0, QString tempFileName = 0 )
01497       : Job (parent, name),
01498         mTempFileName(tempFileName),
01499         mCmd(cmd),
01500         mMsg( aMsg )
01501     {
01502     }
01503 
01504     ~PipeJob() {}
01505     virtual void processEvent( KPIM::ThreadWeaver::Event *ev )
01506     {
01507       KPIM::ThreadWeaver::Job::processEvent( ev );
01508       if ( ev->action() == KPIM::ThreadWeaver::Event::JobFinished )
01509         deleteLater( );
01510     }
01511   protected:
01512     void run()
01513     {
01514       KPIM::ThreadWeaver::debug (1, "PipeJob::run: doing it .\n");
01515       FILE *p;
01516       QByteArray ba;
01517 
01518       p = popen(QFile::encodeName(mCmd), "r");
01519       int len =100;
01520       char buffer[100];
01521       // append data to ba:
01522       while (true)  {
01523         if (! fgets( buffer, len, p ) ) break;
01524         int oldsize = ba.size();
01525         ba.resize( oldsize + strlen(buffer) );
01526         qmemmove( ba.begin() + oldsize, buffer, strlen(buffer) );
01527       }
01528       pclose(p);
01529       if ( !ba.isEmpty() ) {
01530         KPIM::ThreadWeaver::debug (1, "PipeJob::run: %s", QString(ba).latin1() );
01531         mMsg->fromByteArray( ba );
01532       }
01533 
01534       KPIM::ThreadWeaver::debug (1, "PipeJob::run: done.\n" );
01535       // unlink the tempFile
01536       QFile::remove(mTempFileName);
01537     }
01538     QString mTempFileName;
01539     QString mCmd;
01540     KMMessage *mMsg;
01541 };
01542 
01543 class KMFilterActionExtFilter: public KMFilterActionWithCommand
01544 {
01545 public:
01546   KMFilterActionExtFilter();
01547   virtual ReturnCode process(KMMessage* msg) const;
01548   virtual void processAsync(KMMessage* msg) const;
01549   static KMFilterAction* newAction(void);
01550 };
01551 
01552 KMFilterAction* KMFilterActionExtFilter::newAction(void)
01553 {
01554   return (new KMFilterActionExtFilter);
01555 }
01556 
01557 KMFilterActionExtFilter::KMFilterActionExtFilter()
01558   : KMFilterActionWithCommand( "filter app", i18n("pipe through") )
01559 {
01560 }
01561 KMFilterAction::ReturnCode KMFilterActionExtFilter::process(KMMessage* aMsg) const
01562 {
01563   return KMFilterActionWithCommand::genericProcess( aMsg, true ); // use output
01564 }
01565 
01566 void KMFilterActionExtFilter::processAsync(KMMessage* aMsg) const
01567 {
01568 
01569   ActionScheduler *handler = MessageProperty::filterHandler( aMsg->getMsgSerNum() );
01570   KTempFile * inFile = new KTempFile;
01571   inFile->setAutoDelete(FALSE);
01572 
01573   QPtrList<KTempFile> atmList;
01574   atmList.setAutoDelete(TRUE);
01575   atmList.append( inFile );
01576 
01577   QString commandLine = substituteCommandLineArgsFor( aMsg , atmList );
01578   if ( commandLine.isEmpty() )
01579     handler->actionMessage( ErrorButGoOn );
01580 
01581   // The parentheses force the creation of a subshell
01582   // in which the user-specified command is executed.
01583   // This is to really catch all output of the command as well
01584   // as to avoid clashes of our redirection with the ones
01585   // the user may have specified. In the long run, we
01586   // shouldn't be using tempfiles at all for this class, due
01587   // to security aspects. (mmutz)
01588   commandLine =  "(" + commandLine + ") <" + inFile->name();
01589 
01590   // write message to file
01591   QString tempFileName = inFile->name();
01592   kCStringToFile( aMsg->asString(), tempFileName, //###
01593       false, false, false );
01594   inFile->close();
01595 
01596   PipeJob *job = new PipeJob(0, 0, aMsg, commandLine, tempFileName);
01597   QObject::connect ( job, SIGNAL( done() ), handler, SLOT( actionMessage() ) );
01598   kmkernel->weaver()->enqueue(job);
01599 }
01600 
01601 //=============================================================================
01602 // KMFilterActionExecSound - execute command
01603 // Execute a sound
01604 //=============================================================================
01605 class KMFilterActionExecSound : public KMFilterActionWithTest
01606 {
01607 public:
01608   KMFilterActionExecSound();
01609   virtual ReturnCode process(KMMessage* msg) const;
01610   virtual bool requiresBody(KMMsgBase*) const;
01611   static KMFilterAction* newAction(void);
01612 };
01613 
01614 KMFilterActionWithTest::KMFilterActionWithTest( const char* aName, const QString aLabel )
01615   : KMFilterAction( aName, aLabel )
01616 {
01617 }
01618 
01619 KMFilterActionWithTest::~KMFilterActionWithTest()
01620 {
01621 }
01622 
01623 QWidget* KMFilterActionWithTest::createParamWidget( QWidget* parent ) const
01624 {
01625   KMSoundTestWidget *le = new KMSoundTestWidget(parent);
01626   le->setUrl( mParameter );
01627   return le;
01628 }
01629 
01630 
01631 void KMFilterActionWithTest::applyParamWidgetValue( QWidget* paramWidget )
01632 {
01633   mParameter = ((KMSoundTestWidget*)paramWidget)->url();
01634 }
01635 
01636 void KMFilterActionWithTest::setParamWidgetValue( QWidget* paramWidget ) const
01637 {
01638   ((KMSoundTestWidget*)paramWidget)->setUrl( mParameter );
01639 }
01640 
01641 void KMFilterActionWithTest::clearParamWidget( QWidget* paramWidget ) const
01642 {
01643   ((KMSoundTestWidget*)paramWidget)->clear();
01644 }
01645 
01646 void KMFilterActionWithTest::argsFromString( const QString argsStr )
01647 {
01648   mParameter = argsStr;
01649 }
01650 
01651 const QString KMFilterActionWithTest::argsAsString() const
01652 {
01653   return mParameter;
01654 }
01655 
01656 
01657 KMFilterActionExecSound::KMFilterActionExecSound()
01658   : KMFilterActionWithTest( "play sound", i18n("play a sound") )
01659 {
01660 }
01661 
01662 KMFilterAction* KMFilterActionExecSound::newAction(void)
01663 {
01664   return (new KMFilterActionExecSound());
01665 }
01666 
01667 KMFilterAction::ReturnCode KMFilterActionExecSound::process(KMMessage*) const
01668 {
01669   if ( mParameter.isEmpty() )
01670     return ErrorButGoOn;
01671   QString play = mParameter;
01672   QString file = QString::fromLatin1("file:");
01673   if (mParameter.startsWith(file))
01674     play = mParameter.mid(file.length());
01675   KAudioPlayer::play(QFile::encodeName(play));
01676   return GoOn;
01677 }
01678 
01679 bool KMFilterActionExecSound::requiresBody(KMMsgBase*) const
01680 {
01681   return false;
01682 }
01683 
01684 KMFilterActionWithUrl::KMFilterActionWithUrl( const char* aName, const QString aLabel )
01685   : KMFilterAction( aName, aLabel )
01686 {
01687 }
01688 
01689 KMFilterActionWithUrl::~KMFilterActionWithUrl()
01690 {
01691 }
01692 
01693 QWidget* KMFilterActionWithUrl::createParamWidget( QWidget* parent ) const
01694 {
01695   KURLRequester *le = new KURLRequester(parent);
01696   le->setURL( mParameter );
01697   return le;
01698 }
01699 
01700 
01701 void KMFilterActionWithUrl::applyParamWidgetValue( QWidget* paramWidget )
01702 {
01703   mParameter = ((KURLRequester*)paramWidget)->url();
01704 }
01705 
01706 void KMFilterActionWithUrl::setParamWidgetValue( QWidget* paramWidget ) const
01707 {
01708   ((KURLRequester*)paramWidget)->setURL( mParameter );
01709 }
01710 
01711 void KMFilterActionWithUrl::clearParamWidget( QWidget* paramWidget ) const
01712 {
01713   ((KURLRequester*)paramWidget)->clear();
01714 }
01715 
01716 void KMFilterActionWithUrl::argsFromString( const QString argsStr )
01717 {
01718   mParameter = argsStr;
01719 }
01720 
01721 const QString KMFilterActionWithUrl::argsAsString() const
01722 {
01723   return mParameter;
01724 }
01725 
01726 
01727 //=============================================================================
01728 //
01729 //   Filter  Action  Dictionary
01730 //
01731 //=============================================================================
01732 void KMFilterActionDict::init(void)
01733 {
01734   insert( KMFilterActionMove::newAction );
01735   insert( KMFilterActionIdentity::newAction );
01736   insert( KMFilterActionSetStatus::newAction );
01737   insert( KMFilterActionFakeDisposition::newAction );
01738   insert( KMFilterActionTransport::newAction );
01739   insert( KMFilterActionReplyTo::newAction );
01740   insert( KMFilterActionForward::newAction );
01741   insert( KMFilterActionRedirect::newAction );
01742   insert( KMFilterActionBounce::newAction );
01743   insert( KMFilterActionSendReceipt::newAction );
01744   insert( KMFilterActionExec::newAction );
01745   insert( KMFilterActionExtFilter::newAction );
01746   insert( KMFilterActionRemoveHeader::newAction );
01747   insert( KMFilterActionAddHeader::newAction );
01748   insert( KMFilterActionRewriteHeader::newAction );
01749   insert( KMFilterActionExecSound::newAction );
01750   // Register custom filter actions below this line.
01751 }
01752 // The int in the QDict constructor (23) must be a prime
01753 // and should be greater than the double number of KMFilterAction types
01754 KMFilterActionDict::KMFilterActionDict()
01755   : QDict<KMFilterActionDesc>(23)
01756 {
01757   mList.setAutoDelete(TRUE);
01758   init();
01759 }
01760 
01761 void KMFilterActionDict::insert( KMFilterActionNewFunc aNewFunc )
01762 {
01763   KMFilterAction *action = aNewFunc();
01764   KMFilterActionDesc* desc = new KMFilterActionDesc;
01765   desc->name = action->name();
01766   desc->label = action->label();
01767   desc->create = aNewFunc;
01768   QDict<KMFilterActionDesc>::insert( desc->name, desc );
01769   QDict<KMFilterActionDesc>::insert( desc->label, desc );
01770   mList.append( desc );
01771   delete action;
01772 }
KDE Logo
This file is part of the documentation for kmail Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:37:25 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003