3 #include "kmfilteraction.h"
5 // other KMail headers:
6 #include "kmcommands.h"
8 #include "kmfiltermgr.h"
9 #include "kmfolderindex.h"
10 #include "kmfoldermgr.h"
11 #include "messagesender.h"
12 #include "kmmainwidget.h"
13 #include <kpimidentities/identity.h>
14 #include <kpimidentities/identitymanager.h>
15 #include <kpimidentities/identitycombo.h>
16 #include <kpimutils/kfileio.h>
17 #include <mimelib/message.h>
18 #include "kmfawidgets.h"
19 #include "folderrequester.h"
20 using KMail::FolderRequester
;
21 #include "kmmsgbase.h"
22 #include "templateparser.h"
23 using KMail::TemplateParser
;
24 #include "messageproperty.h"
25 #include "actionscheduler.h"
26 using KMail::MessageProperty
;
27 using KMail::ActionScheduler
;
28 #include "regexplineedit.h"
29 using KMail::RegExpLineEdit
;
31 #include <ktemporaryfile.h>
34 #include <kurlrequester.h>
35 #include <Phonon/MediaObject>
41 #include <QTextDocument>
47 //=============================================================================
51 //=============================================================================
53 KMFilterAction::KMFilterAction( const char* aName
, const QString
&aLabel
)
59 KMFilterAction::~KMFilterAction()
63 void KMFilterAction::processAsync(KMMessage
* msg
) const
65 ActionScheduler
*handler
= MessageProperty::filterHandler( msg
);
66 ReturnCode result
= process( msg
);
68 handler
->actionMessage( result
);
71 bool KMFilterAction::requiresBody(KMMsgBase
*) const
76 KMFilterAction
* KMFilterAction::newAction()
81 QWidget
* KMFilterAction::createParamWidget(QWidget
* parent
) const
83 return new QWidget(parent
);
86 void KMFilterAction::applyParamWidgetValue(QWidget
*)
90 void KMFilterAction::setParamWidgetValue( QWidget
* ) const
94 void KMFilterAction::clearParamWidget( QWidget
* ) const
98 bool KMFilterAction::folderRemoved(KMFolder
*, KMFolder
*)
103 int KMFilterAction::tempOpenFolder(KMFolder
* aFolder
)
105 return kmkernel
->filterMgr()->tempOpenFolder(aFolder
);
108 void KMFilterAction::sendMDN( KMMessage
* msg
, KMime::MDN::DispositionType d
,
109 const QList
<KMime::MDN::DispositionModifier
> & m
) {
112 /* createMDN requires Return-Path and Disposition-Notification-To
113 * if it is not set in the message we assume that the notification should go to the
116 const QString returnPath
= msg
->headerField( "Return-Path" );
117 const QString dispNoteTo
= msg
->headerField( "Disposition-Notification-To" );
118 if ( returnPath
.isEmpty() )
119 msg
->setHeaderField( "Return-Path", msg
->from() );
120 if ( dispNoteTo
.isEmpty() )
121 msg
->setHeaderField( "Disposition-Notification-To", msg
->from() );
123 KMMessage
* mdn
= msg
->createMDN( KMime::MDN::AutomaticAction
, d
, false, m
);
124 if ( mdn
&& !kmkernel
->msgSender()->send( mdn
, KMail::MessageSender::SendLater
) ) {
125 kDebug(5006) <<"KMFilterAction::sendMDN(): sending failed.";
129 //restore orignial header
130 if ( returnPath
.isEmpty() )
131 msg
->removeHeaderField( "Return-Path" );
132 if ( dispNoteTo
.isEmpty() )
133 msg
->removeHeaderField( "Disposition-Notification-To" );
137 //=============================================================================
139 // KMFilterActionWithNone
141 //=============================================================================
143 KMFilterActionWithNone::KMFilterActionWithNone( const char* aName
, const QString
&aLabel
)
144 : KMFilterAction( aName
, aLabel
)
148 const QString
KMFilterActionWithNone::displayString() const
154 //=============================================================================
156 // KMFilterActionWithUOID
158 //=============================================================================
160 KMFilterActionWithUOID::KMFilterActionWithUOID( const char* aName
, const QString
&aLabel
)
161 : KMFilterAction( aName
, aLabel
), mParameter( 0 )
165 void KMFilterActionWithUOID::argsFromString( const QString
&argsStr
)
167 mParameter
= argsStr
.trimmed().toUInt();
170 const QString
KMFilterActionWithUOID::argsAsString() const
172 return QString::number( mParameter
);
175 const QString
KMFilterActionWithUOID::displayString() const
177 // FIXME after string freeze:
178 // return i18n("").arg( );
179 return label() + " \"" + Qt::escape( argsAsString() ) + "\"";
183 //=============================================================================
185 // KMFilterActionWithString
187 //=============================================================================
189 KMFilterActionWithString::KMFilterActionWithString( const char* aName
, const QString
&aLabel
)
190 : KMFilterAction( aName
, aLabel
)
194 QWidget
* KMFilterActionWithString::createParamWidget( QWidget
* parent
) const
196 QLineEdit
*le
= new KLineEdit(parent
);
197 le
->setText( mParameter
);
201 void KMFilterActionWithString::applyParamWidgetValue( QWidget
* paramWidget
)
203 mParameter
= ((QLineEdit
*)paramWidget
)->text();
206 void KMFilterActionWithString::setParamWidgetValue( QWidget
* paramWidget
) const
208 ((QLineEdit
*)paramWidget
)->setText( mParameter
);
211 void KMFilterActionWithString::clearParamWidget( QWidget
* paramWidget
) const
213 ((QLineEdit
*)paramWidget
)->clear();
216 void KMFilterActionWithString::argsFromString( const QString
&argsStr
)
218 mParameter
= argsStr
;
221 const QString
KMFilterActionWithString::argsAsString() const
226 const QString
KMFilterActionWithString::displayString() const
228 // FIXME after string freeze:
229 // return i18n("").arg( );
230 return label() + " \"" + Qt::escape( argsAsString() ) + "\"";
233 //=============================================================================
235 // class KMFilterActionWithStringList
237 //=============================================================================
239 KMFilterActionWithStringList::KMFilterActionWithStringList( const char* aName
, const QString
&aLabel
)
240 : KMFilterActionWithString( aName
, aLabel
)
244 QWidget
* KMFilterActionWithStringList::createParamWidget( QWidget
* parent
) const
246 QComboBox
*cb
= new QComboBox( parent
);
247 cb
->setEditable( false );
248 cb
->addItems( mParameterList
);
249 setParamWidgetValue( cb
);
253 void KMFilterActionWithStringList::applyParamWidgetValue( QWidget
* paramWidget
)
255 mParameter
= ((QComboBox
*)paramWidget
)->currentText();
258 void KMFilterActionWithStringList::setParamWidgetValue( QWidget
* paramWidget
) const
260 int idx
= mParameterList
.indexOf( mParameter
);
261 ((QComboBox
*)paramWidget
)->setCurrentIndex( idx
>= 0 ? idx
: 0 );
264 void KMFilterActionWithStringList::clearParamWidget( QWidget
* paramWidget
) const
266 ((QComboBox
*)paramWidget
)->setCurrentIndex(0);
269 void KMFilterActionWithStringList::argsFromString( const QString
&argsStr
)
271 int idx
= mParameterList
.indexOf( argsStr
);
273 mParameterList
.append( argsStr
);
274 idx
= mParameterList
.count() - 1;
276 mParameter
= mParameterList
.at( idx
);
280 //=============================================================================
282 // class KMFilterActionWithFolder
284 //=============================================================================
286 KMFilterActionWithFolder::KMFilterActionWithFolder( const char* aName
, const QString
&aLabel
)
287 : KMFilterAction( aName
, aLabel
)
292 QWidget
* KMFilterActionWithFolder::createParamWidget( QWidget
* parent
) const
294 FolderRequester
*req
= new FolderRequester( parent
,
295 kmkernel
->getKMMainWidget()->folderTree() );
296 setParamWidgetValue( req
);
300 void KMFilterActionWithFolder::applyParamWidgetValue( QWidget
* paramWidget
)
302 mFolder
= ((FolderRequester
*)paramWidget
)->folder();
303 mFolderName
= ((FolderRequester
*)paramWidget
)->folderId();
306 void KMFilterActionWithFolder::setParamWidgetValue( QWidget
* paramWidget
) const
309 ((FolderRequester
*)paramWidget
)->setFolder( mFolder
);
311 ((FolderRequester
*)paramWidget
)->setFolder( mFolderName
);
314 void KMFilterActionWithFolder::clearParamWidget( QWidget
* paramWidget
) const
316 ((FolderRequester
*)paramWidget
)->setFolder( kmkernel
->draftsFolder() );
319 void KMFilterActionWithFolder::argsFromString( const QString
&argsStr
)
321 mFolder
= kmkernel
->folderMgr()->findIdString( argsStr
);
323 mFolder
= kmkernel
->dimapFolderMgr()->findIdString( argsStr
);
325 mFolder
= kmkernel
->imapFolderMgr()->findIdString( argsStr
);
327 mFolderName
= mFolder
->idString();
329 mFolderName
= argsStr
;
332 const QString
KMFilterActionWithFolder::argsAsString() const
336 result
= mFolder
->idString();
338 result
= mFolderName
;
342 const QString
KMFilterActionWithFolder::displayString() const
346 result
= mFolder
->prettyUrl();
348 result
= mFolderName
;
349 return label() + " \"" + Qt::escape( result
) + "\"";
352 bool KMFilterActionWithFolder::folderRemoved( KMFolder
* aFolder
, KMFolder
* aNewFolder
)
354 if ( aFolder
== mFolder
) {
355 mFolder
= aNewFolder
;
357 mFolderName
= mFolder
->idString();
363 //=============================================================================
365 // class KMFilterActionWithAddress
367 //=============================================================================
369 KMFilterActionWithAddress::KMFilterActionWithAddress( const char* aName
, const QString
&aLabel
)
370 : KMFilterActionWithString( aName
, aLabel
)
374 QWidget
* KMFilterActionWithAddress::createParamWidget( QWidget
* parent
) const
376 KMFilterActionWithAddressWidget
*w
= new KMFilterActionWithAddressWidget(parent
);
377 w
->setText( mParameter
);
381 void KMFilterActionWithAddress::applyParamWidgetValue( QWidget
* paramWidget
)
383 mParameter
= ((KMFilterActionWithAddressWidget
*)paramWidget
)->text();
386 void KMFilterActionWithAddress::setParamWidgetValue( QWidget
* paramWidget
) const
388 ((KMFilterActionWithAddressWidget
*)paramWidget
)->setText( mParameter
);
391 void KMFilterActionWithAddress::clearParamWidget( QWidget
* paramWidget
) const
393 ((KMFilterActionWithAddressWidget
*)paramWidget
)->clear();
396 //=============================================================================
398 // class KMFilterActionWithCommand
400 //=============================================================================
402 KMFilterActionWithCommand::KMFilterActionWithCommand( const char* aName
, const QString
&aLabel
)
403 : KMFilterActionWithUrl( aName
, aLabel
)
407 QWidget
* KMFilterActionWithCommand::createParamWidget( QWidget
* parent
) const
409 return KMFilterActionWithUrl::createParamWidget( parent
);
412 void KMFilterActionWithCommand::applyParamWidgetValue( QWidget
* paramWidget
)
414 KMFilterActionWithUrl::applyParamWidgetValue( paramWidget
);
417 void KMFilterActionWithCommand::setParamWidgetValue( QWidget
* paramWidget
) const
419 KMFilterActionWithUrl::setParamWidgetValue( paramWidget
);
422 void KMFilterActionWithCommand::clearParamWidget( QWidget
* paramWidget
) const
424 KMFilterActionWithUrl::clearParamWidget( paramWidget
);
427 QString
KMFilterActionWithCommand::substituteCommandLineArgsFor( KMMessage
*aMsg
, QList
<KTemporaryFile
*> & aTempFileList
) const
429 QString result
= mParameter
;
431 QRegExp
r( "%[0-9-]+" );
435 while ( ( start
= r
.indexIn( result
, start
+ 1 ) ) > 0 ) {
436 int len
= r
.matchedLength();
437 // and save the encountered 'n' in a list.
439 int n
= result
.mid( start
+ 1, len
- 1 ).toInt( &OK
);
444 // sort the list of n's
447 // and use QString::arg to substitute filenames for the %n's.
449 QString tempFileName
;
450 for ( QList
<int>::Iterator it
= argList
.begin() ; it
!= argList
.end() ; ++it
) {
451 // setup temp files with check for duplicate %n's
452 if ( (*it
) != lastSeen
) {
453 KTemporaryFile
*tf
= new KTemporaryFile();
456 kDebug(5006) <<"KMFilterActionWithCommand: Could not create temp file!";
459 aTempFileList
.append( tf
);
460 tempFileName
= tf
->fileName();
462 KPIMUtils::kByteArrayToFile( aMsg
->asString(), tempFileName
, //###
463 false, false, false );
464 else if (aMsg
->numBodyParts() == 0)
465 KPIMUtils::kByteArrayToFile( aMsg
->bodyDecodedBinary(), tempFileName
,
466 false, false, false );
468 KMMessagePart msgPart
;
469 aMsg
->bodyPart( (*it
), &msgPart
);
470 KPIMUtils::kByteArrayToFile( msgPart
.bodyDecodedBinary(), tempFileName
,
471 false, false, false );
475 // QString( "%0 and %1 and %1" ).arg( 0 ).arg( 1 )
476 // returns "0 and 1 and %1", so we must call .arg as
477 // many times as there are %n's, regardless of their multiplicity.
478 if ((*it
) == -1) result
.replace( "%-1", tempFileName
);
479 else result
= result
.arg( tempFileName
);
482 // And finally, replace the %{foo} with the content of the foo
484 QRegExp
header_rx( "%\\{([a-z0-9-]+)\\}", Qt::CaseInsensitive
);
486 while ( ( idx
= header_rx
.indexIn( result
, idx
) ) != -1 ) {
487 QString replacement
= KShell::quoteArg( aMsg
->headerField( header_rx
.cap(1).toLatin1() ) );
488 result
.replace( idx
, header_rx
.matchedLength(), replacement
);
489 idx
+= replacement
.length();
496 KMFilterAction::ReturnCode
KMFilterActionWithCommand::genericProcess(KMMessage
* aMsg
, bool withOutput
) const
500 if ( mParameter
.isEmpty() )
503 // K3Process doesn't support a QProcess::launch() equivalent, so
504 // we must use a temp file :-(
505 KTemporaryFile
* inFile
= new KTemporaryFile
;
508 QList
<KTemporaryFile
*> atmList
;
509 atmList
.append( inFile
);
511 QString commandLine
= substituteCommandLineArgsFor( aMsg
, atmList
);
512 if ( commandLine
.isEmpty() )
515 // The parentheses force the creation of a subshell
516 // in which the user-specified command is executed.
517 // This is to really catch all output of the command as well
518 // as to avoid clashes of our redirection with the ones
519 // the user may have specified. In the long run, we
520 // shouldn't be using tempfiles at all for this class, due
521 // to security aspects. (mmutz)
522 commandLine
= '(' + commandLine
+ ") <" + inFile
->fileName();
524 // write message to file
525 QString tempFileName
= inFile
->fileName();
526 KPIMUtils::kByteArrayToFile( aMsg
->asString(), tempFileName
, //###
527 false, false, false );
531 shProc
.setOutputChannelMode( KProcess::SeparateChannels
);
532 shProc
.setShellCommand( commandLine
);
533 int result
= shProc
.execute();
536 qDeleteAll( atmList
);
542 // read altered message:
543 QByteArray msgText
= shProc
.readAllStandardOutput();
545 if ( !msgText
.isEmpty() ) {
546 /* If the pipe through alters the message, it could very well
547 happen that it no longer has a X-UID header afterwards. That is
548 unfortunate, as we need to removed the original from the folder
549 using that, and look it up in the message. When the (new) message
550 is uploaded, the header is stripped anyhow. */
551 QString uid
= aMsg
->headerField("X-UID");
552 aMsg
->fromString( msgText
);
553 aMsg
->setHeaderField("X-UID",uid
);
556 qDeleteAll( atmList
);
561 qDeleteAll( atmList
);
567 //=============================================================================
569 // Specific Filter Actions
571 //=============================================================================
573 //=============================================================================
574 // KMFilterActionSendReceipt - send receipt
575 // Return delivery receipt.
576 //=============================================================================
577 class KMFilterActionSendReceipt
: public KMFilterActionWithNone
580 KMFilterActionSendReceipt();
581 virtual ReturnCode
process(KMMessage
* msg
) const;
582 static KMFilterAction
* newAction(void);
585 KMFilterAction
* KMFilterActionSendReceipt::newAction(void)
587 return (new KMFilterActionSendReceipt
);
590 KMFilterActionSendReceipt::KMFilterActionSendReceipt()
591 : KMFilterActionWithNone( "confirm delivery", i18n("Confirm Delivery") )
595 KMFilterAction::ReturnCode
KMFilterActionSendReceipt::process(KMMessage
* msg
) const
597 KMMessage
*receipt
= msg
->createDeliveryReceipt();
598 if ( !receipt
) return ErrorButGoOn
;
600 // Queue message. This is a) so that the user can check
601 // the receipt before sending and b) for speed reasons.
602 kmkernel
->msgSender()->send( receipt
, KMail::MessageSender::SendLater
);
609 //=============================================================================
610 // KMFilterActionSetTransport - set transport to...
611 // Specify mail transport (smtp server) to be used when replying to a message
612 // TODO: use TransportComboBox so the user does not enter an invalid transport
613 //=============================================================================
614 class KMFilterActionTransport
: public KMFilterActionWithString
617 KMFilterActionTransport();
618 virtual ReturnCode
process(KMMessage
* msg
) const;
619 static KMFilterAction
* newAction(void);
622 KMFilterAction
* KMFilterActionTransport::newAction(void)
624 return (new KMFilterActionTransport
);
627 KMFilterActionTransport::KMFilterActionTransport()
628 : KMFilterActionWithString( "set transport", i18n("Set Transport To") )
632 KMFilterAction::ReturnCode
KMFilterActionTransport::process(KMMessage
* msg
) const
634 if ( mParameter
.isEmpty() )
636 msg
->setHeaderField( "X-KMail-Transport", mParameter
);
641 //=============================================================================
642 // KMFilterActionReplyTo - set Reply-To to
643 // Set the Reply-to header in a message
644 //=============================================================================
645 class KMFilterActionReplyTo
: public KMFilterActionWithString
648 KMFilterActionReplyTo();
649 virtual ReturnCode
process(KMMessage
* msg
) const;
650 static KMFilterAction
* newAction(void);
653 KMFilterAction
* KMFilterActionReplyTo::newAction(void)
655 return (new KMFilterActionReplyTo
);
658 KMFilterActionReplyTo::KMFilterActionReplyTo()
659 : KMFilterActionWithString( "set Reply-To", i18n("Set Reply-To To") )
664 KMFilterAction::ReturnCode
KMFilterActionReplyTo::process(KMMessage
* msg
) const
666 msg
->setHeaderField( "Reply-To", mParameter
);
672 //=============================================================================
673 // KMFilterActionIdentity - set identity to
674 // Specify Identity to be used when replying to a message
675 //=============================================================================
676 class KMFilterActionIdentity
: public KMFilterActionWithUOID
679 KMFilterActionIdentity();
680 virtual ReturnCode
process(KMMessage
* msg
) const;
681 static KMFilterAction
* newAction();
683 QWidget
* createParamWidget( QWidget
* parent
) const;
684 void applyParamWidgetValue( QWidget
* parent
);
685 void setParamWidgetValue( QWidget
* parent
) const;
686 void clearParamWidget( QWidget
* param
) const;
689 KMFilterAction
* KMFilterActionIdentity::newAction()
691 return (new KMFilterActionIdentity
);
694 KMFilterActionIdentity::KMFilterActionIdentity()
695 : KMFilterActionWithUOID( "set identity", i18n("Set Identity To") )
697 mParameter
= kmkernel
->identityManager()->defaultIdentity().uoid();
700 KMFilterAction::ReturnCode
KMFilterActionIdentity::process(KMMessage
* msg
) const
702 msg
->setHeaderField( "X-KMail-Identity", QString::number( mParameter
) );
706 QWidget
* KMFilterActionIdentity::createParamWidget( QWidget
* parent
) const
708 KPIMIdentities::IdentityCombo
* ic
= new KPIMIdentities::IdentityCombo( kmkernel
->identityManager(), parent
);
709 ic
->setCurrentIdentity( mParameter
);
713 void KMFilterActionIdentity::applyParamWidgetValue( QWidget
* paramWidget
)
715 KPIMIdentities::IdentityCombo
* ic
= dynamic_cast<KPIMIdentities::IdentityCombo
*>( paramWidget
);
717 mParameter
= ic
->currentIdentity();
720 void KMFilterActionIdentity::clearParamWidget( QWidget
* paramWidget
) const
722 KPIMIdentities::IdentityCombo
* ic
= dynamic_cast<KPIMIdentities::IdentityCombo
*>( paramWidget
);
724 ic
->setCurrentIndex( 0 );
725 //ic->setCurrentIdentity( kmkernel->identityManager()->defaultIdentity() );
728 void KMFilterActionIdentity::setParamWidgetValue( QWidget
* paramWidget
) const
730 KPIMIdentities::IdentityCombo
* ic
= dynamic_cast<KPIMIdentities::IdentityCombo
*>( paramWidget
);
732 ic
->setCurrentIdentity( mParameter
);
735 //=============================================================================
736 // KMFilterActionSetStatus - set status to
737 // Set the status of messages
738 //=============================================================================
739 class KMFilterActionSetStatus
: public KMFilterActionWithStringList
742 KMFilterActionSetStatus();
743 virtual ReturnCode
process(KMMessage
* msg
) const;
744 virtual bool requiresBody(KMMsgBase
*) const;
746 static KMFilterAction
* newAction();
748 virtual bool isEmpty() const { return false; }
750 virtual void argsFromString( const QString
&argsStr
);
751 virtual const QString
argsAsString() const;
752 virtual const QString
displayString() const;
756 static const MessageStatus stati
[] =
758 MessageStatus::statusImportant(),
759 MessageStatus::statusRead(),
760 MessageStatus::statusUnread(),
761 MessageStatus::statusReplied(),
762 MessageStatus::statusForwarded(),
763 MessageStatus::statusOld(),
764 MessageStatus::statusNew(),
765 MessageStatus::statusWatched(),
766 MessageStatus::statusIgnored(),
767 MessageStatus::statusSpam(),
768 MessageStatus::statusHam()
770 static const int StatiCount
= sizeof( stati
) / sizeof( MessageStatus
);
772 KMFilterAction
* KMFilterActionSetStatus::newAction()
774 return (new KMFilterActionSetStatus
);
777 KMFilterActionSetStatus::KMFilterActionSetStatus()
778 : KMFilterActionWithStringList( "set status", i18n("Mark As") )
780 // if you change this list, also update
781 // KMFilterActionSetStatus::stati above
782 mParameterList
.append( "" );
783 mParameterList
.append( i18nc("msg status","Important") );
784 mParameterList
.append( i18nc("msg status","Read") );
785 mParameterList
.append( i18nc("msg status","Unread") );
786 mParameterList
.append( i18nc("msg status","Replied") );
787 mParameterList
.append( i18nc("msg status","Forwarded") );
788 mParameterList
.append( i18nc("msg status","Old") );
789 mParameterList
.append( i18nc("msg status","New") );
790 mParameterList
.append( i18nc("msg status","Watched") );
791 mParameterList
.append( i18nc("msg status","Ignored") );
792 mParameterList
.append( i18nc("msg status","Spam") );
793 mParameterList
.append( i18nc("msg status","Ham") );
795 mParameter
= mParameterList
.at(0);
798 KMFilterAction::ReturnCode
KMFilterActionSetStatus::process(KMMessage
* msg
) const
800 int idx
= mParameterList
.indexOf( mParameter
);
801 if ( idx
< 1 ) return ErrorButGoOn
;
803 msg
->setStatus( stati
[idx
-1] );
807 bool KMFilterActionSetStatus::requiresBody(KMMsgBase
*) const
812 void KMFilterActionSetStatus::argsFromString( const QString
&argsStr
)
814 if ( argsStr
.length() == 1 ) {
815 MessageStatus status
;
817 for ( i
= 0 ; i
< StatiCount
; i
++ )
820 if ( status
.getStatusStr()[0] == argsStr
[0].toLatin1() ) {
821 mParameter
= mParameterList
.at(i
+1);
826 mParameter
= mParameterList
.at(0);
829 const QString
KMFilterActionSetStatus::argsAsString() const
831 int idx
= mParameterList
.indexOf( mParameter
);
832 if ( idx
< 1 ) return QString();
834 return stati
[idx
-1].getStatusStr();
837 const QString
KMFilterActionSetStatus::displayString() const
839 // FIXME after string freeze:
840 // return i18n("").arg( );
841 return label() + " \"" + Qt::escape( argsAsString() ) + "\"";
844 //=============================================================================
845 // KMFilterActionFakeDisposition - send fake MDN
846 // Sends a fake MDN or forces an ignore.
847 //=============================================================================
848 class KMFilterActionFakeDisposition
: public KMFilterActionWithStringList
851 KMFilterActionFakeDisposition();
852 virtual ReturnCode
process(KMMessage
* msg
) const;
853 static KMFilterAction
* newAction() {
854 return (new KMFilterActionFakeDisposition
);
857 virtual bool isEmpty() const { return false; }
859 virtual void argsFromString( const QString
&argsStr
);
860 virtual const QString
argsAsString() const;
861 virtual const QString
displayString() const;
865 // if you change this list, also update
866 // the count in argsFromString
867 static const KMime::MDN::DispositionType mdns
[] =
869 KMime::MDN::Displayed
,
871 KMime::MDN::Dispatched
,
872 KMime::MDN::Processed
,
876 static const int numMDNs
= sizeof mdns
/ sizeof *mdns
;
879 KMFilterActionFakeDisposition::KMFilterActionFakeDisposition()
880 : KMFilterActionWithStringList( "fake mdn", i18n("Send Fake MDN") )
882 // if you change this list, also update
884 mParameterList
.append( "" );
885 mParameterList
.append( i18nc("MDN type","Ignore") );
886 mParameterList
.append( i18nc("MDN type","Displayed") );
887 mParameterList
.append( i18nc("MDN type","Deleted") );
888 mParameterList
.append( i18nc("MDN type","Dispatched") );
889 mParameterList
.append( i18nc("MDN type","Processed") );
890 mParameterList
.append( i18nc("MDN type","Denied") );
891 mParameterList
.append( i18nc("MDN type","Failed") );
893 mParameter
= mParameterList
.at(0);
896 KMFilterAction::ReturnCode
KMFilterActionFakeDisposition::process(KMMessage
* msg
) const
898 int idx
= mParameterList
.indexOf( mParameter
);
899 if ( idx
< 1 ) return ErrorButGoOn
;
901 if ( idx
== 1 ) // ignore
902 msg
->setMDNSentState( KMMsgMDNIgnore
);
904 sendMDN( msg
, mdns
[idx
-2] ); // skip first two entries: "" and "ignore"
908 void KMFilterActionFakeDisposition::argsFromString( const QString
&argsStr
)
910 if ( argsStr
.length() == 1 ) {
911 if ( argsStr
[0] == 'I' ) { // ignore
912 mParameter
= mParameterList
.at(1);
915 for ( int i
= 0 ; i
< numMDNs
; i
++ )
916 if ( char(mdns
[i
]) == argsStr
[0] ) { // send
917 mParameter
= mParameterList
.at(i
+2);
921 mParameter
= mParameterList
.at(0);
924 const QString
KMFilterActionFakeDisposition::argsAsString() const
926 int idx
= mParameterList
.indexOf( mParameter
);
927 if ( idx
< 1 ) return QString();
929 return QString( QChar( idx
< 2 ? 'I' : char(mdns
[idx
-2]) ) );
932 const QString
KMFilterActionFakeDisposition::displayString() const
934 // FIXME after string freeze:
935 // return i18n("").arg( );
936 return label() + " \"" + Qt::escape( argsAsString() ) + "\"";
939 //=============================================================================
940 // KMFilterActionRemoveHeader - remove header
941 // Remove all instances of the given header field.
942 //=============================================================================
943 class KMFilterActionRemoveHeader
: public KMFilterActionWithStringList
946 KMFilterActionRemoveHeader();
947 virtual ReturnCode
process(KMMessage
* msg
) const;
948 virtual QWidget
* createParamWidget( QWidget
* parent
) const;
949 virtual void setParamWidgetValue( QWidget
* paramWidget
) const;
951 static KMFilterAction
* newAction();
954 KMFilterAction
* KMFilterActionRemoveHeader::newAction()
956 return (new KMFilterActionRemoveHeader
);
959 KMFilterActionRemoveHeader::KMFilterActionRemoveHeader()
960 : KMFilterActionWithStringList( "remove header", i18n("Remove Header") )
965 << "X-KDE-PR-Message"
966 << "X-KDE-PR-Package"
967 << "X-KDE-PR-Keywords";
968 mParameter
= mParameterList
.at(0);
971 QWidget
* KMFilterActionRemoveHeader::createParamWidget( QWidget
* parent
) const
973 QComboBox
*cb
= new QComboBox( parent
);
974 cb
->setEditable( true );
975 cb
->setInsertPolicy( QComboBox::AtBottom
);
976 setParamWidgetValue( cb
);
980 KMFilterAction::ReturnCode
KMFilterActionRemoveHeader::process(KMMessage
* msg
) const
982 if ( mParameter
.isEmpty() ) return ErrorButGoOn
;
984 while ( !msg
->headerField( mParameter
.toLatin1() ).isEmpty() )
985 msg
->removeHeaderField( mParameter
.toLatin1() );
989 void KMFilterActionRemoveHeader::setParamWidgetValue( QWidget
* paramWidget
) const
991 QComboBox
* cb
= dynamic_cast<QComboBox
*>(paramWidget
);
994 int idx
= mParameterList
.indexOf( mParameter
);
996 cb
->addItems( mParameterList
);
998 cb
->addItem( mParameter
);
999 cb
->setCurrentIndex( cb
->count() - 1 );
1001 cb
->setCurrentIndex( idx
);
1006 //=============================================================================
1007 // KMFilterActionAddHeader - add header
1008 // Add a header with the given value.
1009 //=============================================================================
1010 class KMFilterActionAddHeader
: public KMFilterActionWithStringList
1013 KMFilterActionAddHeader();
1014 virtual ReturnCode
process(KMMessage
* msg
) const;
1015 virtual QWidget
* createParamWidget( QWidget
* parent
) const;
1016 virtual void setParamWidgetValue( QWidget
* paramWidget
) const;
1017 virtual void applyParamWidgetValue( QWidget
* paramWidget
);
1018 virtual void clearParamWidget( QWidget
* paramWidget
) const;
1020 virtual const QString
argsAsString() const;
1021 virtual void argsFromString( const QString
&argsStr
);
1023 virtual const QString
displayString() const;
1025 static KMFilterAction
* newAction()
1027 return (new KMFilterActionAddHeader
);
1033 KMFilterActionAddHeader::KMFilterActionAddHeader()
1034 : KMFilterActionWithStringList( "add header", i18n("Add Header") )
1036 mParameterList
<< ""
1039 << "X-KDE-PR-Message"
1040 << "X-KDE-PR-Package"
1041 << "X-KDE-PR-Keywords";
1042 mParameter
= mParameterList
.at(0);
1045 KMFilterAction::ReturnCode
KMFilterActionAddHeader::process(KMMessage
* msg
) const
1047 if ( mParameter
.isEmpty() ) return ErrorButGoOn
;
1049 msg
->setHeaderField( mParameter
.toLatin1(), mValue
);
1053 QWidget
* KMFilterActionAddHeader::createParamWidget( QWidget
* parent
) const
1055 QWidget
*w
= new QWidget( parent
);
1056 QHBoxLayout
*hbl
= new QHBoxLayout( w
);
1057 hbl
->setSpacing( 4 );
1058 hbl
->setMargin( 0 );
1059 QComboBox
*cb
= new QComboBox( w
);
1060 cb
->setObjectName( "combo" );
1061 cb
->setEditable( true );
1062 cb
->setInsertPolicy( QComboBox::AtBottom
);
1063 hbl
->addWidget( cb
, 0 /* stretch */ );
1064 QLabel
*l
= new QLabel( i18n("With value:"), w
);
1065 l
->setFixedWidth( l
->sizeHint().width() );
1066 hbl
->addWidget( l
, 0 );
1067 QLineEdit
*le
= new KLineEdit( w
);
1068 le
->setObjectName( "ledit" );
1069 hbl
->addWidget( le
, 1 );
1070 setParamWidgetValue( w
);
1074 void KMFilterActionAddHeader::setParamWidgetValue( QWidget
* paramWidget
) const
1076 int idx
= mParameterList
.indexOf( mParameter
);
1077 QComboBox
*cb
= paramWidget
->findChild
<QComboBox
*>("combo");
1080 cb
->addItems( mParameterList
);
1082 cb
->addItem( mParameter
);
1083 cb
->setCurrentIndex( cb
->count() - 1 );
1085 cb
->setCurrentIndex( idx
);
1087 QLineEdit
*le
= paramWidget
->findChild
<QLineEdit
*>("ledit");
1089 le
->setText( mValue
);
1092 void KMFilterActionAddHeader::applyParamWidgetValue( QWidget
* paramWidget
)
1094 QComboBox
*cb
= paramWidget
->findChild
<QComboBox
*>("combo");
1096 mParameter
= cb
->currentText();
1098 QLineEdit
*le
= paramWidget
->findChild
<QLineEdit
*>("ledit");
1100 mValue
= le
->text();
1103 void KMFilterActionAddHeader::clearParamWidget( QWidget
* paramWidget
) const
1105 QComboBox
*cb
= paramWidget
->findChild
<QComboBox
*>("combo");
1107 cb
->setCurrentIndex(0);
1108 QLineEdit
*le
= paramWidget
->findChild
<QLineEdit
*>("ledit");
1113 const QString
KMFilterActionAddHeader::argsAsString() const
1115 QString result
= mParameter
;
1122 const QString
KMFilterActionAddHeader::displayString() const
1124 // FIXME after string freeze:
1125 // return i18n("").arg( );
1126 return label() + " \"" + Qt::escape( argsAsString() ) + "\"";
1129 void KMFilterActionAddHeader::argsFromString( const QString
&argsStr
)
1131 QStringList l
= argsStr
.split( '\t' );
1133 if ( l
.count() < 2 ) {
1141 int idx
= mParameterList
.indexOf( s
);
1143 mParameterList
.append( s
);
1144 idx
= mParameterList
.count() - 1;
1146 mParameter
= mParameterList
.at( idx
);
1150 //=============================================================================
1151 // KMFilterActionRewriteHeader - rewrite header
1152 // Rewrite a header using a regexp.
1153 //=============================================================================
1154 class KMFilterActionRewriteHeader
: public KMFilterActionWithStringList
1157 KMFilterActionRewriteHeader();
1158 virtual ReturnCode
process(KMMessage
* msg
) const;
1159 virtual QWidget
* createParamWidget( QWidget
* parent
) const;
1160 virtual void setParamWidgetValue( QWidget
* paramWidget
) const;
1161 virtual void applyParamWidgetValue( QWidget
* paramWidget
);
1162 virtual void clearParamWidget( QWidget
* paramWidget
) const;
1164 virtual const QString
argsAsString() const;
1165 virtual void argsFromString( const QString
&argsStr
);
1167 virtual const QString
displayString() const;
1169 static KMFilterAction
* newAction()
1171 return (new KMFilterActionRewriteHeader
);
1175 QString mReplacementString
;
1178 KMFilterActionRewriteHeader::KMFilterActionRewriteHeader()
1179 : KMFilterActionWithStringList( "rewrite header", i18n("Rewrite Header") )
1181 mParameterList
<< ""
1185 << "X-KDE-PR-Message"
1186 << "X-KDE-PR-Package"
1187 << "X-KDE-PR-Keywords";
1188 mParameter
= mParameterList
.at(0);
1191 KMFilterAction::ReturnCode
KMFilterActionRewriteHeader::process(KMMessage
* msg
) const
1193 if ( mParameter
.isEmpty() || !mRegExp
.isValid() )
1194 return ErrorButGoOn
;
1195 // QString::replace is not const.
1196 QString value
= msg
->headerField( mParameter
.toLatin1() );
1197 msg
->setHeaderField( mParameter
.toLatin1(), value
.replace( mRegExp
, mReplacementString
) );
1201 QWidget
* KMFilterActionRewriteHeader::createParamWidget( QWidget
* parent
) const
1203 QWidget
*w
= new QWidget( parent
);
1204 QHBoxLayout
*hbl
= new QHBoxLayout( w
);
1205 hbl
->setSpacing( 4 );
1206 hbl
->setMargin( 0 );
1208 QComboBox
*cb
= new QComboBox( w
);
1209 cb
->setEditable( true );
1210 cb
->setObjectName( "combo" );
1211 cb
->setInsertPolicy( QComboBox::AtBottom
);
1212 hbl
->addWidget( cb
, 0 /* stretch */ );
1214 QLabel
*l
= new QLabel( i18n("Replace:"), w
);
1215 l
->setFixedWidth( l
->sizeHint().width() );
1216 hbl
->addWidget( l
, 0 );
1218 RegExpLineEdit
*rele
= new RegExpLineEdit( w
);
1219 rele
->setObjectName( "search" );
1220 hbl
->addWidget( rele
, 1 );
1222 l
= new QLabel( i18n("With:"), w
);
1223 l
->setFixedWidth( l
->sizeHint().width() );
1224 hbl
->addWidget( l
, 0 );
1226 QLineEdit
*le
= new KLineEdit( w
);
1227 le
->setObjectName( "replace" );
1228 hbl
->addWidget( le
, 1 );
1230 setParamWidgetValue( w
);
1234 void KMFilterActionRewriteHeader::setParamWidgetValue( QWidget
* paramWidget
) const
1236 int idx
= mParameterList
.indexOf( mParameter
);
1237 QComboBox
*cb
= paramWidget
->findChild
<QComboBox
*>("combo");
1241 cb
->addItems( mParameterList
);
1243 cb
->addItem( mParameter
);
1244 cb
->setCurrentIndex( cb
->count() - 1 );
1246 cb
->setCurrentIndex( idx
);
1249 RegExpLineEdit
*rele
= paramWidget
->findChild
<RegExpLineEdit
*>("search");
1251 rele
->setText( mRegExp
.pattern() );
1253 QLineEdit
*le
= paramWidget
->findChild
<QLineEdit
*>("replace");
1255 le
->setText( mReplacementString
);
1258 void KMFilterActionRewriteHeader::applyParamWidgetValue( QWidget
* paramWidget
)
1260 QComboBox
*cb
= paramWidget
->findChild
<QComboBox
*>("combo");
1262 mParameter
= cb
->currentText();
1264 RegExpLineEdit
*rele
= paramWidget
->findChild
<RegExpLineEdit
*>("search");
1266 mRegExp
.setPattern( rele
->text() );
1268 QLineEdit
*le
= paramWidget
->findChild
<QLineEdit
*>("replace");
1270 mReplacementString
= le
->text();
1273 void KMFilterActionRewriteHeader::clearParamWidget( QWidget
* paramWidget
) const
1275 QComboBox
*cb
= paramWidget
->findChild
<QComboBox
*>("combo");
1277 cb
->setCurrentIndex(0);
1279 RegExpLineEdit
*rele
= paramWidget
->findChild
<RegExpLineEdit
*>("search");
1283 QLineEdit
*le
= paramWidget
->findChild
<QLineEdit
*>("replace");
1288 const QString
KMFilterActionRewriteHeader::argsAsString() const
1290 QString result
= mParameter
;
1292 result
+= mRegExp
.pattern();
1294 result
+= mReplacementString
;
1299 const QString
KMFilterActionRewriteHeader::displayString() const
1301 // FIXME after string freeze:
1302 // return i18n("").arg( );
1303 return label() + " \"" + Qt::escape( argsAsString() ) + "\"";
1306 void KMFilterActionRewriteHeader::argsFromString( const QString
&argsStr
)
1308 QStringList l
= argsStr
.split( '\t' );
1312 mRegExp
.setPattern( l
[1] );
1313 mReplacementString
= l
[2];
1315 int idx
= mParameterList
.indexOf( s
);
1317 mParameterList
.append( s
);
1318 idx
= mParameterList
.count() - 1;
1320 mParameter
= mParameterList
.at( idx
);
1324 //=============================================================================
1325 // KMFilterActionMove - move into folder
1326 // File message into another mail folder
1327 //=============================================================================
1328 class KMFilterActionMove
: public KMFilterActionWithFolder
1331 KMFilterActionMove();
1332 virtual ReturnCode
process(KMMessage
* msg
) const;
1333 virtual bool requiresBody(KMMsgBase
*) const;
1334 static KMFilterAction
* newAction(void);
1337 KMFilterAction
* KMFilterActionMove::newAction(void)
1339 return (new KMFilterActionMove
);
1342 KMFilterActionMove::KMFilterActionMove()
1343 : KMFilterActionWithFolder( "transfer", i18n("Move Into Folder") )
1347 KMFilterAction::ReturnCode
KMFilterActionMove::process(KMMessage
* msg
) const
1350 return ErrorButGoOn
;
1352 ActionScheduler
*handler
= MessageProperty::filterHandler( msg
);
1354 MessageProperty::setFilterFolder( msg
, mFolder
);
1356 // The old filtering system does not support online imap targets.
1357 // Skip online imap targets when using the old system.
1359 check
= kmkernel
->imapFolderMgr()->findIdString( argsAsString() );
1360 if (mFolder
&& (check
!= mFolder
)) {
1361 MessageProperty::setFilterFolder( msg
, mFolder
);
1367 bool KMFilterActionMove::requiresBody(KMMsgBase
*) const
1369 return false; //iff mFolder->folderMgr == msgBase->parent()->folderMgr;
1373 //=============================================================================
1374 // KMFilterActionCopy - copy into folder
1375 // Copy message into another mail folder
1376 //=============================================================================
1377 class KMFilterActionCopy
: public KMFilterActionWithFolder
1380 KMFilterActionCopy();
1381 virtual ReturnCode
process(KMMessage
* msg
) const;
1382 virtual void processAsync(KMMessage
* msg
) const;
1383 virtual bool requiresBody(KMMsgBase
*) const;
1384 static KMFilterAction
* newAction(void);
1387 KMFilterAction
* KMFilterActionCopy::newAction( void )
1389 return ( new KMFilterActionCopy
);
1392 KMFilterActionCopy::KMFilterActionCopy()
1393 : KMFilterActionWithFolder( "copy", i18n("Copy Into Folder") )
1397 KMFilterAction::ReturnCode
KMFilterActionCopy::process( KMMessage
*msg
) const
1399 // TODO opening and closing the folder is a trade off.
1400 // Perhaps Copy is a seldomly used action for now,
1401 // but I gonna look at improvements ASAP.
1402 if ( !mFolder
|| mFolder
->open( "filtercopy" ) != 0 ) {
1403 return ErrorButGoOn
;
1406 // copy the message 1:1
1407 KMMessage
* msgCopy
= new KMMessage( new DwMessage( *msg
->asDwMessage() ) );
1410 int rc
= mFolder
->addMsg( msgCopy
, &index
);
1411 if ( rc
== 0 && index
!= -1 ) {
1412 mFolder
->unGetMsg( index
);
1414 mFolder
->close( "filtercopy" );
1419 void KMFilterActionCopy::processAsync( KMMessage
*msg
) const
1421 ActionScheduler
*handler
= MessageProperty::filterHandler( msg
);
1423 KMCommand
*cmd
= new KMCopyCommand( mFolder
, msg
);
1424 QObject::connect( cmd
, SIGNAL( completed( KMCommand
* ) ),
1425 handler
, SLOT( copyMessageFinished( KMCommand
* ) ) );
1429 bool KMFilterActionCopy::requiresBody( KMMsgBase
*msg
) const
1435 //=============================================================================
1436 // KMFilterActionForward - forward to
1437 // Forward message to another user
1438 //=============================================================================
1439 class KMFilterActionForward
: public KMFilterActionWithAddress
1442 KMFilterActionForward();
1443 virtual ReturnCode
process( KMMessage
*msg
) const;
1444 static KMFilterAction
* newAction( void );
1447 KMFilterAction
*KMFilterActionForward::newAction( void )
1449 return ( new KMFilterActionForward
);
1452 KMFilterActionForward::KMFilterActionForward()
1453 : KMFilterActionWithAddress( "forward", i18n("Forward To") )
1457 KMFilterAction::ReturnCode
KMFilterActionForward::process( KMMessage
*aMsg
) const
1459 if ( mParameter
.isEmpty() )
1460 return ErrorButGoOn
;
1462 // avoid endless loops when this action is used in a filter
1463 // which applies to sent messages
1464 if ( KMMessage::addressIsInAddressList( mParameter
, QStringList( aMsg
->to() ) ) )
1465 return ErrorButGoOn
;
1467 // Create the forwarded message by hand to make forwarding of messages with
1468 // attachments work.
1469 // Note: This duplicates a lot of code from KMMessage::createForward() and
1470 // KMComposeWin::applyChanges().
1471 // ### FIXME: Remove the code duplication again.
1473 KMMessage
* msg
= new KMMessage
;
1475 msg
->initFromMessage( aMsg
);
1477 // QString st = QString::fromUtf8( aMsg->createForwardBody() );
1478 TemplateParser
parser( msg
, TemplateParser::Forward
,
1479 aMsg
->body(), false, false, false);
1480 parser
.process( aMsg
);
1483 encoding
= KMMsgBase::autoDetectCharset( aMsg
->charset(),
1484 KMMessage::preferredCharsets(),
1486 if( encoding
.isEmpty() )
1488 QByteArray str
= KMMsgBase::codecForName( encoding
)->fromUnicode( msg
->body() );
1490 msg
->setCharset( encoding
);
1491 msg
->setTo( mParameter
);
1492 msg
->setSubject( "Fwd: " + aMsg
->subject() );
1494 bool isQP
= kmkernel
->msgSender()->sendQuotedPrintable();
1496 if( aMsg
->numBodyParts() == 0 )
1498 msg
->setAutomaticFields( true );
1499 msg
->setHeaderField( "Content-Type", "text/plain" );
1500 // msg->setCteStr( isQP ? "quoted-printable": "8bit" );
1502 msg
->setBodyAndGuessCte(str
, dummy
, !isQP
);
1503 msg
->setCharset( encoding
);
1505 msg
->setBodyEncoded( str
);
1507 msg
->setBody( str
);
1511 KMMessagePart bodyPart
, msgPart
;
1513 msg
->removeHeaderField( "Content-Type" );
1514 msg
->removeHeaderField( "Content-Transfer-Encoding" );
1515 msg
->setAutomaticFields( true );
1516 msg
->setBody( "This message is in MIME format.\n\n" );
1518 bodyPart
.setTypeStr( "text" );
1519 bodyPart
.setSubtypeStr( "plain" );
1520 // bodyPart.setCteStr( isQP ? "quoted-printable": "8bit" );
1522 bodyPart
.setBodyAndGuessCte(str
, dummy
, !isQP
);
1523 bodyPart
.setCharset( encoding
);
1524 bodyPart
.setBodyEncoded( str
);
1525 msg
->addBodyPart( &bodyPart
);
1527 for( int i
= 0; i
< aMsg
->numBodyParts(); i
++ )
1529 aMsg
->bodyPart( i
, &msgPart
);
1530 if( i
> 0 || qstricmp( msgPart
.typeStr(), "text" ) != 0 )
1531 msg
->addBodyPart( &msgPart
);
1534 msg
->cleanupHeader();
1535 msg
->link( aMsg
, MessageStatus::statusForwarded() );
1537 sendMDN( aMsg
, KMime::MDN::Dispatched
);
1539 if ( !kmkernel
->msgSender()->send( msg
, KMail::MessageSender::SendLater
) ) {
1540 kDebug(5006) <<"KMFilterAction: could not forward message (sending failed)";
1541 return ErrorButGoOn
; // error: couldn't send
1547 //=============================================================================
1548 // KMFilterActionRedirect - redirect to
1549 // Redirect message to another user
1550 //=============================================================================
1551 class KMFilterActionRedirect
: public KMFilterActionWithAddress
1554 KMFilterActionRedirect();
1555 virtual ReturnCode
process(KMMessage
* msg
) const;
1556 static KMFilterAction
* newAction(void);
1559 KMFilterAction
* KMFilterActionRedirect::newAction(void)
1561 return (new KMFilterActionRedirect
);
1564 KMFilterActionRedirect::KMFilterActionRedirect()
1565 : KMFilterActionWithAddress( "redirect", i18n("Redirect To") )
1569 KMFilterAction::ReturnCode
KMFilterActionRedirect::process(KMMessage
* aMsg
) const
1572 if ( mParameter
.isEmpty() )
1573 return ErrorButGoOn
;
1575 msg
= aMsg
->createRedirect( mParameter
);
1577 sendMDN( aMsg
, KMime::MDN::Dispatched
);
1579 if ( !kmkernel
->msgSender()->send( msg
, KMail::MessageSender::SendLater
) ) {
1580 kDebug(5006) <<"KMFilterAction: could not redirect message (sending failed)";
1581 return ErrorButGoOn
; // error: couldn't send
1587 //=============================================================================
1588 // KMFilterActionExec - execute command
1589 // Execute a shell command
1590 //=============================================================================
1591 class KMFilterActionExec
: public KMFilterActionWithCommand
1594 KMFilterActionExec();
1595 virtual ReturnCode
process(KMMessage
* msg
) const;
1596 static KMFilterAction
* newAction(void);
1599 KMFilterAction
* KMFilterActionExec::newAction(void)
1601 return (new KMFilterActionExec());
1604 KMFilterActionExec::KMFilterActionExec()
1605 : KMFilterActionWithCommand( "execute", i18n("Execute Command") )
1609 KMFilterAction::ReturnCode
KMFilterActionExec::process(KMMessage
*aMsg
) const
1611 return KMFilterActionWithCommand::genericProcess( aMsg
, false ); // ignore output
1614 //=============================================================================
1615 // KMFilterActionExtFilter - use external filter app
1616 // External message filter: executes a shell command with message
1617 // on stdin; altered message is expected on stdout.
1618 //=============================================================================
1620 #include <threadweaver/ThreadWeaver.h>
1621 #include <threadweaver/Job.h>
1622 #include <threadweaver/DebuggingAids.h>
1623 class PipeJob
: public ThreadWeaver::Job
1626 PipeJob(QObject
* parent
= 0 , KMMessage
* aMsg
= 0, QString cmd
= 0, QString tempFileName
= 0 )
1627 : ThreadWeaver::Job ( parent
),
1628 mTempFileName( tempFileName
),
1636 virtual void done( ThreadWeaver::Job
*job
)
1638 ThreadWeaver::Job::done( job
);
1645 ThreadWeaver::debug (1, "PipeJob::run: doing it .\n");
1649 // backup the serial number in case the header gets lost
1650 QString origSerNum
= mMsg
->headerField( "X-KMail-Filtered" );
1652 p
= popen(QFile::encodeName(mCmd
), "r");
1655 // append data to ba:
1657 if (! fgets( buffer
, len
, p
) ) break;
1658 int oldsize
= ba
.size();
1659 ba
.resize( oldsize
+ strlen(buffer
) );
1660 qmemmove( ba
.begin() + oldsize
, buffer
, strlen(buffer
) );
1663 if ( !ba
.isEmpty() ) {
1664 ThreadWeaver::debug (1, "PipeJob::run: %s", ba
.constData() );
1665 KMFolder
*filterFolder
= mMsg
->parent();
1666 ActionScheduler
*handler
= MessageProperty::filterHandler( mMsg
->getMsgSerNum() );
1668 mMsg
->fromString( ba
);
1669 if ( !origSerNum
.isEmpty() )
1670 mMsg
->setHeaderField( "X-KMail-Filtered", origSerNum
);
1671 if ( filterFolder
&& handler
) {
1672 bool oldStatus
= handler
->ignoreChanges( true );
1673 filterFolder
->take( filterFolder
->find( mMsg
) );
1674 filterFolder
->addMsg( mMsg
);
1675 handler
->ignoreChanges( oldStatus
);
1677 kDebug(5006) <<"Warning: Cannot refresh the message from the external filter.";
1681 ThreadWeaver::debug (1, "PipeJob::run: done.\n" );
1682 // unlink the tempFile
1683 QFile::remove(mTempFileName
);
1686 QString mTempFileName
;
1691 class KMFilterActionExtFilter
: public KMFilterActionWithCommand
1694 KMFilterActionExtFilter();
1695 virtual ReturnCode
process(KMMessage
* msg
) const;
1696 virtual void processAsync(KMMessage
* msg
) const;
1697 static KMFilterAction
* newAction(void);
1700 KMFilterAction
* KMFilterActionExtFilter::newAction(void)
1702 return (new KMFilterActionExtFilter
);
1705 KMFilterActionExtFilter::KMFilterActionExtFilter()
1706 : KMFilterActionWithCommand( "filter app", i18n("Pipe Through") )
1709 KMFilterAction::ReturnCode
KMFilterActionExtFilter::process(KMMessage
* aMsg
) const
1711 return KMFilterActionWithCommand::genericProcess( aMsg
, true ); // use output
1714 void KMFilterActionExtFilter::processAsync(KMMessage
* aMsg
) const
1717 ActionScheduler
*handler
= MessageProperty::filterHandler( aMsg
->getMsgSerNum() );
1718 KTemporaryFile
*inFile
= new KTemporaryFile
;
1719 inFile
->setAutoRemove(false);
1722 QList
<KTemporaryFile
*> atmList
;
1723 atmList
.append( inFile
);
1725 QString commandLine
= substituteCommandLineArgsFor( aMsg
, atmList
);
1726 qDeleteAll( atmList
);
1728 if ( commandLine
.isEmpty() )
1729 handler
->actionMessage( ErrorButGoOn
);
1731 // The parentheses force the creation of a subshell
1732 // in which the user-specified command is executed.
1733 // This is to really catch all output of the command as well
1734 // as to avoid clashes of our redirection with the ones
1735 // the user may have specified. In the long run, we
1736 // shouldn't be using tempfiles at all for this class, due
1737 // to security aspects. (mmutz)
1738 commandLine
= '(' + commandLine
+ ") <" + inFile
->fileName();
1740 // write message to file
1741 QString tempFileName
= inFile
->fileName();
1742 KPIMUtils::kByteArrayToFile( aMsg
->asString(), tempFileName
, //###
1743 false, false, false );
1746 PipeJob
*job
= new PipeJob(0, aMsg
, commandLine
, tempFileName
);
1747 QObject::connect ( job
, SIGNAL( done() ), handler
, SLOT( actionMessage() ) );
1748 kmkernel
->weaver()->enqueue(job
);
1751 //=============================================================================
1752 // KMFilterActionExecSound - execute command
1754 //=============================================================================
1755 class KMFilterActionExecSound
: public KMFilterActionWithTest
1758 KMFilterActionExecSound();
1759 ~KMFilterActionExecSound();
1760 virtual ReturnCode
process(KMMessage
* msg
) const;
1761 virtual bool requiresBody(KMMsgBase
*) const;
1762 static KMFilterAction
* newAction(void);
1764 Phonon::MediaObject
* mPlayer
;
1767 KMFilterActionWithTest::KMFilterActionWithTest( const char* aName
, const QString
&aLabel
)
1768 : KMFilterAction( aName
, aLabel
)
1772 KMFilterActionWithTest::~KMFilterActionWithTest()
1776 QWidget
* KMFilterActionWithTest::createParamWidget( QWidget
* parent
) const
1778 KMSoundTestWidget
*le
= new KMSoundTestWidget(parent
);
1779 le
->setUrl( mParameter
);
1784 void KMFilterActionWithTest::applyParamWidgetValue( QWidget
* paramWidget
)
1786 mParameter
= ((KMSoundTestWidget
*)paramWidget
)->url();
1789 void KMFilterActionWithTest::setParamWidgetValue( QWidget
* paramWidget
) const
1791 ((KMSoundTestWidget
*)paramWidget
)->setUrl( mParameter
);
1794 void KMFilterActionWithTest::clearParamWidget( QWidget
* paramWidget
) const
1796 ((KMSoundTestWidget
*)paramWidget
)->clear();
1799 void KMFilterActionWithTest::argsFromString( const QString
&argsStr
)
1801 mParameter
= argsStr
;
1804 const QString
KMFilterActionWithTest::argsAsString() const
1809 const QString
KMFilterActionWithTest::displayString() const
1811 // FIXME after string freeze:
1812 // return i18n("").arg( );
1813 return label() + " \"" + Qt::escape( argsAsString() ) + "\"";
1817 KMFilterActionExecSound::KMFilterActionExecSound()
1818 : KMFilterActionWithTest( "play sound", i18n("Play Sound") )
1820 mPlayer
= Phonon::createPlayer(Phonon::NotificationCategory
);
1823 KMFilterActionExecSound::~KMFilterActionExecSound()
1828 KMFilterAction
* KMFilterActionExecSound::newAction(void)
1830 return (new KMFilterActionExecSound());
1833 KMFilterAction::ReturnCode
KMFilterActionExecSound::process(KMMessage
*) const
1835 if ( mParameter
.isEmpty() )
1836 return ErrorButGoOn
;
1837 mPlayer
->setCurrentSource( mParameter
);
1842 bool KMFilterActionExecSound::requiresBody(KMMsgBase
*) const
1847 KMFilterActionWithUrl::KMFilterActionWithUrl( const char* aName
, const QString
&aLabel
)
1848 : KMFilterAction( aName
, aLabel
)
1852 KMFilterActionWithUrl::~KMFilterActionWithUrl()
1856 QWidget
* KMFilterActionWithUrl::createParamWidget( QWidget
* parent
) const
1858 KUrlRequester
*le
= new KUrlRequester(parent
);
1859 le
->setPath( mParameter
);
1864 void KMFilterActionWithUrl::applyParamWidgetValue( QWidget
* paramWidget
)
1866 mParameter
= ((KUrlRequester
*)paramWidget
)->url().path();
1869 void KMFilterActionWithUrl::setParamWidgetValue( QWidget
* paramWidget
) const
1871 ((KUrlRequester
*)paramWidget
)->setPath( mParameter
);
1874 void KMFilterActionWithUrl::clearParamWidget( QWidget
* paramWidget
) const
1876 ((KUrlRequester
*)paramWidget
)->clear();
1879 void KMFilterActionWithUrl::argsFromString( const QString
&argsStr
)
1881 mParameter
= argsStr
;
1884 const QString
KMFilterActionWithUrl::argsAsString() const
1889 const QString
KMFilterActionWithUrl::displayString() const
1891 // FIXME after string freeze:
1892 // return i18n("").arg( );
1893 return label() + " \"" + Qt::escape( argsAsString() ) + "\"";
1897 //=============================================================================
1899 // Filter Action Dictionary
1901 //=============================================================================
1902 KMFilterActionDict::~KMFilterActionDict()
1904 qDeleteAll( mList
);
1907 void KMFilterActionDict::init(void)
1909 insert( KMFilterActionMove::newAction
);
1910 insert( KMFilterActionCopy::newAction
);
1911 insert( KMFilterActionIdentity::newAction
);
1912 insert( KMFilterActionSetStatus::newAction
);
1913 insert( KMFilterActionFakeDisposition::newAction
);
1914 insert( KMFilterActionTransport::newAction
);
1915 insert( KMFilterActionReplyTo::newAction
);
1916 insert( KMFilterActionForward::newAction
);
1917 insert( KMFilterActionRedirect::newAction
);
1918 insert( KMFilterActionSendReceipt::newAction
);
1919 insert( KMFilterActionExec::newAction
);
1920 insert( KMFilterActionExtFilter::newAction
);
1921 insert( KMFilterActionRemoveHeader::newAction
);
1922 insert( KMFilterActionAddHeader::newAction
);
1923 insert( KMFilterActionRewriteHeader::newAction
);
1924 insert( KMFilterActionExecSound::newAction
);
1925 // Register custom filter actions below this line.
1927 // The int in the QDict constructor (41) must be a prime
1928 // and should be greater than the double number of KMFilterAction types
1929 KMFilterActionDict::KMFilterActionDict()
1930 : QMultiHash
<QString
, KMFilterActionDesc
*>()
1935 void KMFilterActionDict::insert( KMFilterActionNewFunc aNewFunc
)
1937 KMFilterAction
*action
= aNewFunc();
1938 KMFilterActionDesc
* desc
= new KMFilterActionDesc
;
1939 desc
->name
= action
->name();
1940 desc
->label
= action
->label();
1941 desc
->create
= aNewFunc
;
1942 QMultiHash
<QString
, KMFilterActionDesc
*>::insert( desc
->name
, desc
);
1943 QMultiHash
<QString
, KMFilterActionDesc
*>::insert( desc
->label
, desc
);
1944 mList
.append( desc
);