kmail Library API Documentation

kmfilteraction.cpp

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