You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2424 lines
73 KiB
2424 lines
73 KiB
// kmfilteraction.cpp |
|
|
|
#include "kmfilteraction.h" |
|
#include "config-kmail.h" |
|
|
|
// other KMail headers: |
|
#include "customtemplates.h" |
|
#include "customtemplates_kfg.h" |
|
#include "kmcommands.h" |
|
#include "kmfiltermgr.h" |
|
#include "messagesender.h" |
|
#include "kmmainwidget.h" |
|
#include "kmfawidgets.h" |
|
#include "folderrequester.h" |
|
#include "util.h" |
|
|
|
using KMail::FolderRequester; |
|
#include "messageproperty.h" |
|
#include "actionscheduler.h" |
|
using KMail::MessageProperty; |
|
using KMail::ActionScheduler; |
|
#include "regexplineedit.h" |
|
using KMail::RegExpLineEdit; |
|
#include "stringutil.h" |
|
#include "messageviewer/stringutil.h" |
|
|
|
#include "messagehelper.h" |
|
#include "messageinfo.h" |
|
|
|
// KDE PIM libs headers |
|
#include <kpimidentities/identity.h> |
|
#include <kpimidentities/identitymanager.h> |
|
#include <kpimidentities/identitycombo.h> |
|
#include <kpimutils/kfileio.h> |
|
#include <kpimutils/email.h> |
|
#include <akonadi/itemcopyjob.h> |
|
#include <akonadi/itemmodifyjob.h> |
|
|
|
// KDE headers |
|
#include <kcombobox.h> |
|
#include <ktemporaryfile.h> |
|
#include <kdebug.h> |
|
#include <klocale.h> |
|
#include <kurlrequester.h> |
|
#include <phonon/mediaobject.h> |
|
#include <kshell.h> |
|
#include <kprocess.h> |
|
#include <kabc/addressbook.h> |
|
#include <kabc/stdaddressbook.h> |
|
#include <kabc/resource.h> |
|
#include <nepomuk/tag.h> |
|
|
|
#include <kmime/kmime_message.h> |
|
|
|
// Qt headers: |
|
#include <QTextCodec> |
|
#include <QTextDocument> |
|
|
|
// other headers: |
|
#include <assert.h> |
|
#include <string.h> |
|
|
|
//============================================================================= |
|
// |
|
// KMFilterAction |
|
// |
|
//============================================================================= |
|
|
|
KMFilterAction::KMFilterAction( const char* aName, const QString &aLabel ) |
|
{ |
|
mName = aName; |
|
mLabel = aLabel; |
|
} |
|
|
|
KMFilterAction::~KMFilterAction() |
|
{ |
|
} |
|
|
|
void KMFilterAction::processAsync( const Akonadi::Item &item ) const |
|
{ |
|
ActionScheduler *handler = MessageProperty::filterHandler( item ); |
|
ReturnCode result = process( item ); |
|
if (handler) |
|
handler->actionMessage( result ); |
|
} |
|
|
|
bool KMFilterAction::requiresBody(KMime::Content *) const |
|
{ |
|
return true; |
|
} |
|
|
|
KMFilterAction* KMFilterAction::newAction() |
|
{ |
|
return 0; |
|
} |
|
|
|
QWidget* KMFilterAction::createParamWidget(QWidget* parent) const |
|
{ |
|
return new QWidget(parent); |
|
} |
|
|
|
void KMFilterAction::applyParamWidgetValue(QWidget*) |
|
{ |
|
} |
|
|
|
void KMFilterAction::setParamWidgetValue( QWidget * ) const |
|
{ |
|
} |
|
|
|
void KMFilterAction::clearParamWidget( QWidget * ) const |
|
{ |
|
} |
|
|
|
bool KMFilterAction::folderRemoved(const Akonadi::Collection&, const Akonadi::Collection&) |
|
{ |
|
return false; |
|
} |
|
|
|
void KMFilterAction::sendMDN( const KMime::Message::Ptr &msg, KMime::MDN::DispositionType d, |
|
const QList<KMime::MDN::DispositionModifier> & m ) { |
|
if ( !msg ) return; |
|
|
|
/* createMDN requires Return-Path and Disposition-Notification-To |
|
* if it is not set in the message we assume that the notification should go to the |
|
* sender |
|
*/ |
|
const QString returnPath = msg->headerByType( "Return-Path" ) ? msg->headerByType( "Return-Path ")->asUnicodeString() : ""; |
|
const QString dispNoteTo = msg->headerByType( "Disposition-Notification-To" )? msg->headerByType( "Disposition-Notification-To ")->asUnicodeString() : ""; |
|
if ( returnPath.isEmpty() ) { |
|
KMime::Headers::Generic *header = new KMime::Headers::Generic( "Return-Path", msg.get(), msg->from()->asUnicodeString(), "utf-8" ); |
|
msg->setHeader( header ); |
|
} |
|
if ( dispNoteTo.isEmpty() ) { |
|
KMime::Headers::Generic *header = new KMime::Headers::Generic( "Disposition-Notification-To", msg.get(), msg->from()->asUnicodeString(), "utf-8" ); |
|
msg->setHeader( header ); |
|
} |
|
|
|
kDebug() << "AKONADI PORT: verify Akonadi::Item() here " << Q_FUNC_INFO; |
|
KMime::Message::Ptr mdn = KMail::MessageHelper::createMDN( Akonadi::Item(), msg, KMime::MDN::AutomaticAction, d, false, m ); |
|
if ( mdn && !kmkernel->msgSender()->send( mdn, KMail::MessageSender::SendLater ) ) { |
|
kDebug() << "Sending failed."; |
|
//delete mdn; |
|
} |
|
|
|
//restore orignial header |
|
if ( returnPath.isEmpty() ) |
|
msg->removeHeader( "Return-Path" ); |
|
if ( dispNoteTo.isEmpty() ) |
|
msg->removeHeader( "Disposition-Notification-To" ); |
|
} |
|
|
|
|
|
//============================================================================= |
|
// |
|
// KMFilterActionWithNone |
|
// |
|
//============================================================================= |
|
|
|
KMFilterActionWithNone::KMFilterActionWithNone( const char* aName, const QString &aLabel ) |
|
: KMFilterAction( aName, aLabel ) |
|
{ |
|
} |
|
|
|
const QString KMFilterActionWithNone::displayString() const |
|
{ |
|
return label(); |
|
} |
|
|
|
|
|
//============================================================================= |
|
// |
|
// KMFilterActionWithUOID |
|
// |
|
//============================================================================= |
|
|
|
KMFilterActionWithUOID::KMFilterActionWithUOID( const char* aName, const QString &aLabel ) |
|
: KMFilterAction( aName, aLabel ), mParameter( 0 ) |
|
{ |
|
} |
|
|
|
void KMFilterActionWithUOID::argsFromString( const QString &argsStr ) |
|
{ |
|
mParameter = argsStr.trimmed().toUInt(); |
|
} |
|
|
|
const QString KMFilterActionWithUOID::argsAsString() const |
|
{ |
|
return QString::number( mParameter ); |
|
} |
|
|
|
const QString KMFilterActionWithUOID::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
|
|
//============================================================================= |
|
// |
|
// KMFilterActionWithString |
|
// |
|
//============================================================================= |
|
|
|
KMFilterActionWithString::KMFilterActionWithString( const char* aName, const QString &aLabel ) |
|
: KMFilterAction( aName, aLabel ) |
|
{ |
|
} |
|
|
|
QWidget* KMFilterActionWithString::createParamWidget( QWidget* parent ) const |
|
{ |
|
KLineEdit *le = new KLineEdit(parent); |
|
le->setClearButtonShown( true ); |
|
le->setText( mParameter ); |
|
return le; |
|
} |
|
|
|
void KMFilterActionWithString::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
mParameter = ((KLineEdit*)paramWidget)->text(); |
|
} |
|
|
|
void KMFilterActionWithString::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
((KLineEdit*)paramWidget)->setText( mParameter ); |
|
} |
|
|
|
void KMFilterActionWithString::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
((KLineEdit*)paramWidget)->clear(); |
|
} |
|
|
|
void KMFilterActionWithString::argsFromString( const QString &argsStr ) |
|
{ |
|
mParameter = argsStr; |
|
} |
|
|
|
const QString KMFilterActionWithString::argsAsString() const |
|
{ |
|
return mParameter; |
|
} |
|
|
|
const QString KMFilterActionWithString::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
//============================================================================= |
|
// |
|
// class KMFilterActionWithStringList |
|
// |
|
//============================================================================= |
|
|
|
KMFilterActionWithStringList::KMFilterActionWithStringList( const char* aName, const QString &aLabel ) |
|
: KMFilterActionWithString( aName, aLabel ) |
|
{ |
|
} |
|
|
|
QWidget* KMFilterActionWithStringList::createParamWidget( QWidget* parent ) const |
|
{ |
|
KComboBox *cb = new KComboBox( parent ); |
|
cb->setEditable( false ); |
|
cb->addItems( mParameterList ); |
|
setParamWidgetValue( cb ); |
|
return cb; |
|
} |
|
|
|
void KMFilterActionWithStringList::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
mParameter = ((KComboBox*)paramWidget)->currentText(); |
|
} |
|
|
|
void KMFilterActionWithStringList::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
int idx = mParameterList.indexOf( mParameter ); |
|
((KComboBox*)paramWidget)->setCurrentIndex( idx >= 0 ? idx : 0 ); |
|
} |
|
|
|
void KMFilterActionWithStringList::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
((KComboBox*)paramWidget)->setCurrentIndex(0); |
|
} |
|
|
|
void KMFilterActionWithStringList::argsFromString( const QString &argsStr ) |
|
{ |
|
int idx = mParameterList.indexOf( argsStr ); |
|
if ( idx < 0 ) { |
|
mParameterList.append( argsStr ); |
|
idx = mParameterList.count() - 1; |
|
} |
|
mParameter = mParameterList.at( idx ); |
|
} |
|
|
|
|
|
//============================================================================= |
|
// |
|
// class KMFilterActionWithFolder |
|
// |
|
//============================================================================= |
|
|
|
KMFilterActionWithFolder::KMFilterActionWithFolder( const char* aName, const QString &aLabel ) |
|
: KMFilterAction( aName, aLabel ) |
|
{ |
|
} |
|
|
|
QWidget* KMFilterActionWithFolder::createParamWidget( QWidget* parent ) const |
|
{ |
|
FolderRequester *req = new FolderRequester( parent ); |
|
setParamWidgetValue( req ); |
|
return req; |
|
} |
|
|
|
void KMFilterActionWithFolder::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
mFolder = ((FolderRequester *)paramWidget)->folderCollection(); |
|
mFolderName = ((FolderRequester *)paramWidget)->folderId(); |
|
} |
|
|
|
void KMFilterActionWithFolder::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
if ( mFolder.isValid() ) |
|
((FolderRequester *)paramWidget)->setFolder( mFolder ); |
|
else |
|
((FolderRequester *)paramWidget)->setFolder( mFolderName ); |
|
} |
|
|
|
void KMFilterActionWithFolder::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
((FolderRequester *)paramWidget)->setFolder( kmkernel->draftsCollectionFolder() ); |
|
} |
|
|
|
void KMFilterActionWithFolder::argsFromString( const QString &argsStr ) |
|
{ |
|
mFolder = kmkernel->findFolderCollectionById( argsStr ); |
|
if ( mFolder.isValid() ) |
|
mFolderName= QString::number(mFolder.id()); |
|
else |
|
mFolderName = argsStr; |
|
} |
|
|
|
const QString KMFilterActionWithFolder::argsAsString() const |
|
{ |
|
QString result; |
|
if ( mFolder.isValid() ) |
|
result = QString::number(mFolder.id()); |
|
else |
|
result = mFolderName; |
|
return result; |
|
} |
|
|
|
const QString KMFilterActionWithFolder::displayString() const |
|
{ |
|
QString result; |
|
if ( mFolder.isValid() ) |
|
result = mFolder.url().path(); |
|
else |
|
result = mFolderName; |
|
return label() + " \"" + Qt::escape( result ) + "\""; |
|
} |
|
|
|
bool KMFilterActionWithFolder::folderRemoved( const Akonadi::Collection& aFolder, const Akonadi::Collection& aNewFolder ) |
|
{ |
|
if ( aFolder == mFolder ) { |
|
mFolder = aNewFolder; |
|
if ( aNewFolder.isValid() ) |
|
mFolderName = mFolder.id(); |
|
return true; |
|
} else |
|
return false; |
|
} |
|
|
|
//============================================================================= |
|
// |
|
// class KMFilterActionWithAddress |
|
// |
|
//============================================================================= |
|
|
|
KMFilterActionWithAddress::KMFilterActionWithAddress( const char* aName, const QString &aLabel ) |
|
: KMFilterActionWithString( aName, aLabel ) |
|
{ |
|
} |
|
|
|
QWidget* KMFilterActionWithAddress::createParamWidget( QWidget* parent ) const |
|
{ |
|
KMFilterActionWithAddressWidget *w = new KMFilterActionWithAddressWidget(parent); |
|
w->setText( mParameter ); |
|
return w; |
|
} |
|
|
|
void KMFilterActionWithAddress::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
mParameter = ((KMFilterActionWithAddressWidget*)paramWidget)->text(); |
|
} |
|
|
|
void KMFilterActionWithAddress::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
((KMFilterActionWithAddressWidget*)paramWidget)->setText( mParameter ); |
|
} |
|
|
|
void KMFilterActionWithAddress::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
((KMFilterActionWithAddressWidget*)paramWidget)->clear(); |
|
} |
|
|
|
//============================================================================= |
|
// |
|
// class KMFilterActionWithCommand |
|
// |
|
//============================================================================= |
|
|
|
KMFilterActionWithCommand::KMFilterActionWithCommand( const char* aName, const QString &aLabel ) |
|
: KMFilterActionWithUrl( aName, aLabel ) |
|
{ |
|
} |
|
|
|
QWidget* KMFilterActionWithCommand::createParamWidget( QWidget* parent ) const |
|
{ |
|
return KMFilterActionWithUrl::createParamWidget( parent ); |
|
} |
|
|
|
void KMFilterActionWithCommand::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
KMFilterActionWithUrl::applyParamWidgetValue( paramWidget ); |
|
} |
|
|
|
void KMFilterActionWithCommand::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
KMFilterActionWithUrl::setParamWidgetValue( paramWidget ); |
|
} |
|
|
|
void KMFilterActionWithCommand::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
KMFilterActionWithUrl::clearParamWidget( paramWidget ); |
|
} |
|
|
|
QString KMFilterActionWithCommand::substituteCommandLineArgsFor( const KMime::Message::Ptr &aMsg, QList<KTemporaryFile*> & aTempFileList ) const |
|
{ |
|
QString result = mParameter; |
|
QList<int> argList; |
|
QRegExp r( "%[0-9-]+" ); |
|
|
|
// search for '%n' |
|
int start = -1; |
|
while ( ( start = r.indexIn( result, start + 1 ) ) > 0 ) { |
|
int len = r.matchedLength(); |
|
// and save the encountered 'n' in a list. |
|
bool OK = false; |
|
int n = result.mid( start + 1, len - 1 ).toInt( &OK ); |
|
if ( OK ) |
|
argList.append( n ); |
|
} |
|
|
|
// sort the list of n's |
|
qSort( argList ); |
|
|
|
// and use QString::arg to substitute filenames for the %n's. |
|
int lastSeen = -2; |
|
QString tempFileName; |
|
for ( QList<int>::Iterator it = argList.begin() ; it != argList.end() ; ++it ) { |
|
// setup temp files with check for duplicate %n's |
|
if ( (*it) != lastSeen ) { |
|
KTemporaryFile *tf = new KTemporaryFile(); |
|
if ( !tf->open() ) { |
|
delete tf; |
|
kDebug() << "KMFilterActionWithCommand: Could not create temp file!"; |
|
return QString(); |
|
} |
|
aTempFileList.append( tf ); |
|
tempFileName = tf->fileName(); |
|
if ((*it) == -1) |
|
KPIMUtils::kByteArrayToFile( aMsg->encodedContent(), tempFileName, //### |
|
false, false, false ); |
|
else if (aMsg->contents().size() == 0) |
|
KPIMUtils::kByteArrayToFile( aMsg->decodedContent(), tempFileName, |
|
false, false, false ); |
|
else { |
|
KMime::Content content; |
|
#if 0 //TODO port to akonadi |
|
aMsg->bodyPart( (*it), &msgPart ); |
|
KPIMUtils::kByteArrayToFile( msgPart.bodyDecodedBinary(), tempFileName, |
|
false, false, false ); |
|
#else |
|
kDebug() << "AKONADI PORT: Disabled code in " << Q_FUNC_INFO; |
|
#endif |
|
} |
|
tf->close(); |
|
} |
|
// QString( "%0 and %1 and %1" ).arg( 0 ).arg( 1 ) |
|
// returns "0 and 1 and %1", so we must call .arg as |
|
// many times as there are %n's, regardless of their multiplicity. |
|
if ((*it) == -1) result.replace( "%-1", tempFileName ); |
|
else result = result.arg( tempFileName ); |
|
} |
|
|
|
// And finally, replace the %{foo} with the content of the foo |
|
// header field: |
|
QRegExp header_rx( "%\\{([a-z0-9-]+)\\}", Qt::CaseInsensitive ); |
|
int idx = 0; |
|
while ( ( idx = header_rx.indexIn( result, idx ) ) != -1 ) { |
|
QString replacement = KShell::quoteArg( aMsg->headerByType( header_rx.cap(1).toLatin1() ) ? aMsg->headerByType( header_rx.cap(1).toLatin1() )->as7BitString(): ""); |
|
result.replace( idx, header_rx.matchedLength(), replacement ); |
|
idx += replacement.length(); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
|
|
KMFilterAction::ReturnCode KMFilterActionWithCommand::genericProcess( const Akonadi::Item &item, bool withOutput ) const |
|
{ |
|
const KMime::Message::Ptr aMsg = item.payload<KMime::Message::Ptr>(); |
|
Q_ASSERT( aMsg ); |
|
|
|
if ( mParameter.isEmpty() ) |
|
return ErrorButGoOn; |
|
|
|
// KProcess doesn't support a QProcess::launch() equivalent, so |
|
// we must use a temp file :-( |
|
KTemporaryFile * inFile = new KTemporaryFile; |
|
if ( !inFile->open() ) |
|
return ErrorButGoOn; |
|
|
|
QList<KTemporaryFile*> atmList; |
|
atmList.append( inFile ); |
|
|
|
QString commandLine = substituteCommandLineArgsFor( aMsg, atmList ); |
|
if ( commandLine.isEmpty() ) |
|
{ |
|
qDeleteAll( atmList ); |
|
atmList.clear(); |
|
return ErrorButGoOn; |
|
} |
|
// The parentheses force the creation of a subshell |
|
// in which the user-specified command is executed. |
|
// This is to really catch all output of the command as well |
|
// as to avoid clashes of our redirection with the ones |
|
// the user may have specified. In the long run, we |
|
// shouldn't be using tempfiles at all for this class, due |
|
// to security aspects. (mmutz) |
|
commandLine = '(' + commandLine + ") <" + inFile->fileName(); |
|
|
|
// write message to file |
|
QString tempFileName = inFile->fileName(); |
|
if ( !KPIMUtils::kByteArrayToFile( aMsg->encodedContent(), tempFileName, //### |
|
false, false, false ) ) { |
|
qDeleteAll( atmList ); |
|
atmList.clear(); |
|
return CriticalError; |
|
} |
|
inFile->close(); |
|
|
|
KProcess shProc; |
|
shProc.setOutputChannelMode( KProcess::SeparateChannels ); |
|
shProc.setShellCommand( commandLine ); |
|
int result = shProc.execute(); |
|
|
|
if ( result != 0 ) { |
|
qDeleteAll( atmList ); |
|
atmList.clear(); |
|
return ErrorButGoOn; |
|
} |
|
|
|
if ( withOutput ) { |
|
// read altered message: |
|
QByteArray msgText = shProc.readAllStandardOutput(); |
|
|
|
if ( !msgText.isEmpty() ) { |
|
/* If the pipe through alters the message, it could very well |
|
happen that it no longer has a X-UID header afterwards. That is |
|
unfortunate, as we need to removed the original from the folder |
|
using that, and look it up in the message. When the (new) message |
|
is uploaded, the header is stripped anyhow. */ |
|
QString uid = aMsg->headerByType( "X-UID" ) ?aMsg->headerByType( "X-UID")->asUnicodeString() : "" ; |
|
aMsg->setContent( msgText ); |
|
|
|
KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-UID", aMsg.get(), uid, "utf-8" ); |
|
aMsg->setHeader( header ); |
|
} |
|
else { |
|
qDeleteAll( atmList ); |
|
atmList.clear(); |
|
return ErrorButGoOn; |
|
} |
|
} |
|
qDeleteAll( atmList ); |
|
atmList.clear(); |
|
return GoOn; |
|
} |
|
|
|
|
|
//============================================================================= |
|
// |
|
// Specific Filter Actions |
|
// |
|
//============================================================================= |
|
|
|
//============================================================================= |
|
// KMFilterActionSendReceipt - send receipt |
|
// Return delivery receipt. |
|
//============================================================================= |
|
class KMFilterActionSendReceipt : public KMFilterActionWithNone |
|
{ |
|
public: |
|
KMFilterActionSendReceipt(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction(void); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionSendReceipt::newAction(void) |
|
{ |
|
return (new KMFilterActionSendReceipt); |
|
} |
|
|
|
KMFilterActionSendReceipt::KMFilterActionSendReceipt() |
|
: KMFilterActionWithNone( "confirm delivery", i18n("Confirm Delivery") ) |
|
{ |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionSendReceipt::process( const Akonadi::Item &item ) const |
|
{ |
|
const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
const KMime::Message::Ptr receipt = KMail::MessageHelper::createDeliveryReceipt( item, msg ); |
|
if ( !receipt ) return ErrorButGoOn; |
|
|
|
// Queue message. This is a) so that the user can check |
|
// the receipt before sending and b) for speed reasons. |
|
kmkernel->msgSender()->send( receipt, KMail::MessageSender::SendLater ); |
|
|
|
return GoOn; |
|
} |
|
|
|
|
|
|
|
//============================================================================= |
|
// KMFilterActionSetTransport - set transport to... |
|
// Specify mail transport (smtp server) to be used when replying to a message |
|
// TODO: use TransportComboBox so the user does not enter an invalid transport |
|
//============================================================================= |
|
class KMFilterActionTransport: public KMFilterActionWithString |
|
{ |
|
public: |
|
KMFilterActionTransport(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction(void); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionTransport::newAction(void) |
|
{ |
|
return (new KMFilterActionTransport); |
|
} |
|
|
|
KMFilterActionTransport::KMFilterActionTransport() |
|
: KMFilterActionWithString( "set transport", i18n("Set Transport To") ) |
|
{ |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionTransport::process( const Akonadi::Item &item ) const |
|
{ |
|
if ( mParameter.isEmpty() ) |
|
return ErrorButGoOn; |
|
const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Transport", msg.get(), mParameter, "utf-8"); |
|
msg->setHeader( header ); |
|
return GoOn; |
|
} |
|
|
|
|
|
//============================================================================= |
|
// KMFilterActionReplyTo - set Reply-To to |
|
// Set the Reply-to header in a message |
|
//============================================================================= |
|
class KMFilterActionReplyTo: public KMFilterActionWithString |
|
{ |
|
public: |
|
KMFilterActionReplyTo(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction(void); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionReplyTo::newAction(void) |
|
{ |
|
return (new KMFilterActionReplyTo); |
|
} |
|
|
|
KMFilterActionReplyTo::KMFilterActionReplyTo() |
|
: KMFilterActionWithString( "set Reply-To", i18n("Set Reply-To To") ) |
|
{ |
|
mParameter = ""; |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionReplyTo::process( const Akonadi::Item &item ) const |
|
{ |
|
const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
KMime::Headers::Generic *header = new KMime::Headers::Generic( "Reply-To", msg.get(), mParameter, "utf-8"); |
|
msg->setHeader( header ); |
|
return GoOn; |
|
} |
|
|
|
|
|
|
|
//============================================================================= |
|
// KMFilterActionIdentity - set identity to |
|
// Specify Identity to be used when replying to a message |
|
//============================================================================= |
|
class KMFilterActionIdentity: public KMFilterActionWithUOID |
|
{ |
|
public: |
|
KMFilterActionIdentity(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction(); |
|
|
|
QWidget * createParamWidget( QWidget * parent ) const; |
|
void applyParamWidgetValue( QWidget * parent ); |
|
void setParamWidgetValue( QWidget * parent ) const; |
|
void clearParamWidget( QWidget * param ) const; |
|
}; |
|
|
|
KMFilterAction* KMFilterActionIdentity::newAction() |
|
{ |
|
return (new KMFilterActionIdentity); |
|
} |
|
|
|
KMFilterActionIdentity::KMFilterActionIdentity() |
|
: KMFilterActionWithUOID( "set identity", i18n("Set Identity To") ) |
|
{ |
|
mParameter = kmkernel->identityManager()->defaultIdentity().uoid(); |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionIdentity::process( const Akonadi::Item &item ) const |
|
{ |
|
const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Identity", msg.get(), QString::number(mParameter), "utf-8"); |
|
msg->setHeader( header ); |
|
return GoOn; |
|
} |
|
|
|
QWidget * KMFilterActionIdentity::createParamWidget( QWidget * parent ) const |
|
{ |
|
KPIMIdentities::IdentityCombo * ic = new KPIMIdentities::IdentityCombo( kmkernel->identityManager(), parent ); |
|
ic->setCurrentIdentity( mParameter ); |
|
return ic; |
|
} |
|
|
|
void KMFilterActionIdentity::applyParamWidgetValue( QWidget * paramWidget ) |
|
{ |
|
KPIMIdentities::IdentityCombo * ic = dynamic_cast<KPIMIdentities::IdentityCombo*>( paramWidget ); |
|
assert( ic ); |
|
mParameter = ic->currentIdentity(); |
|
} |
|
|
|
void KMFilterActionIdentity::clearParamWidget( QWidget * paramWidget ) const |
|
{ |
|
KPIMIdentities::IdentityCombo * ic = dynamic_cast<KPIMIdentities::IdentityCombo*>( paramWidget ); |
|
assert( ic ); |
|
ic->setCurrentIndex( 0 ); |
|
//ic->setCurrentIdentity( kmkernel->identityManager()->defaultIdentity() ); |
|
} |
|
|
|
void KMFilterActionIdentity::setParamWidgetValue( QWidget * paramWidget ) const |
|
{ |
|
KPIMIdentities::IdentityCombo * ic = dynamic_cast<KPIMIdentities::IdentityCombo*>( paramWidget ); |
|
assert( ic ); |
|
ic->setCurrentIdentity( mParameter ); |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionSetStatus - set status to |
|
// Set the status of messages |
|
//============================================================================= |
|
class KMFilterActionSetStatus: public KMFilterActionWithStringList |
|
{ |
|
public: |
|
KMFilterActionSetStatus(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual bool requiresBody(KMime::Content*) const; |
|
|
|
static KMFilterAction* newAction(); |
|
|
|
virtual bool isEmpty() const { return false; } |
|
|
|
virtual void argsFromString( const QString &argsStr ); |
|
virtual const QString argsAsString() const; |
|
virtual const QString displayString() const; |
|
}; |
|
|
|
|
|
static const MessageStatus stati[] = |
|
{ |
|
MessageStatus::statusImportant(), |
|
MessageStatus::statusRead(), |
|
MessageStatus::statusUnread(), |
|
MessageStatus::statusReplied(), |
|
MessageStatus::statusForwarded(), |
|
MessageStatus::statusOld(), |
|
MessageStatus::statusNew(), |
|
MessageStatus::statusWatched(), |
|
MessageStatus::statusIgnored(), |
|
MessageStatus::statusSpam(), |
|
MessageStatus::statusHam(), |
|
MessageStatus::statusToAct() |
|
}; |
|
static const int StatiCount = sizeof( stati ) / sizeof( MessageStatus ); |
|
|
|
KMFilterAction* KMFilterActionSetStatus::newAction() |
|
{ |
|
return (new KMFilterActionSetStatus); |
|
} |
|
|
|
KMFilterActionSetStatus::KMFilterActionSetStatus() |
|
: KMFilterActionWithStringList( "set status", i18n("Mark As") ) |
|
{ |
|
// if you change this list, also update |
|
// KMFilterActionSetStatus::stati above |
|
mParameterList.append( "" ); |
|
mParameterList.append( i18nc("msg status","Important") ); |
|
mParameterList.append( i18nc("msg status","Read") ); |
|
mParameterList.append( i18nc("msg status","Unread") ); |
|
mParameterList.append( i18nc("msg status","Replied") ); |
|
mParameterList.append( i18nc("msg status","Forwarded") ); |
|
mParameterList.append( i18nc("msg status","Old") ); |
|
mParameterList.append( i18nc("msg status","New") ); |
|
mParameterList.append( i18nc("msg status","Watched") ); |
|
mParameterList.append( i18nc("msg status","Ignored") ); |
|
mParameterList.append( i18nc("msg status","Spam") ); |
|
mParameterList.append( i18nc("msg status","Ham") ); |
|
mParameterList.append( i18nc("msg status","Action Item") ); |
|
|
|
mParameter = mParameterList.at(0); |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionSetStatus::process( const Akonadi::Item &item ) const |
|
{ |
|
int idx = mParameterList.indexOf( mParameter ); |
|
if ( idx < 1 ) return ErrorButGoOn; |
|
|
|
KPIM::MessageStatus status; |
|
status.set( stati[ idx ] ); |
|
Akonadi::Item i( item ); |
|
i.setFlags( status.getStatusFlags() ); |
|
new Akonadi::ItemModifyJob( i, kmkernel->filterMgr() ); // TODO handle error |
|
return GoOn; |
|
} |
|
|
|
bool KMFilterActionSetStatus::requiresBody(KMime::Content*) const |
|
{ |
|
return false; |
|
} |
|
|
|
void KMFilterActionSetStatus::argsFromString( const QString &argsStr ) |
|
{ |
|
if ( argsStr.length() == 1 ) { |
|
MessageStatus status; |
|
int i; |
|
for ( i = 0 ; i < StatiCount ; i++ ) |
|
{ |
|
status = stati[i]; |
|
if ( status.getStatusStr()[0] == argsStr[0].toLatin1() ) { |
|
mParameter = mParameterList.at(i+1); |
|
return; |
|
} |
|
} |
|
} |
|
mParameter = mParameterList.at(0); |
|
} |
|
|
|
const QString KMFilterActionSetStatus::argsAsString() const |
|
{ |
|
int idx = mParameterList.indexOf( mParameter ); |
|
if ( idx < 1 ) return QString(); |
|
|
|
return stati[idx-1].getStatusStr(); |
|
} |
|
|
|
const QString KMFilterActionSetStatus::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionAddTag - append tag to message |
|
// Appends a tag to messages |
|
//============================================================================= |
|
class KMFilterActionAddTag: public KMFilterActionWithStringList |
|
{ |
|
public: |
|
KMFilterActionAddTag(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual bool requiresBody( KMime::Content* ) const; |
|
|
|
static KMFilterAction* newAction(); |
|
|
|
virtual bool isEmpty() const { return false; } |
|
|
|
virtual void argsFromString( const QString &argsStr ); |
|
virtual const QString argsAsString() const; |
|
virtual const QString displayString() const; |
|
|
|
private: |
|
QStringList mLabelList; |
|
}; |
|
|
|
KMFilterAction* KMFilterActionAddTag::newAction() |
|
{ |
|
return (new KMFilterActionAddTag); |
|
} |
|
|
|
KMFilterActionAddTag::KMFilterActionAddTag() |
|
: KMFilterActionWithStringList( "add tag", i18n("Add Tag") ) |
|
{ |
|
foreach( const Nepomuk::Tag &tag, Nepomuk::Tag::allTags() ) { |
|
mParameterList.append( tag.label() ); |
|
mLabelList.append( tag.resourceUri().toString() ); |
|
} |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionAddTag::process( const Akonadi::Item &item ) const |
|
{ |
|
const int idx = mParameterList.indexOf( mParameter ); |
|
if ( idx == -1 ) return ErrorButGoOn; |
|
|
|
Nepomuk::Resource n_resource( item.url() ); |
|
n_resource.addTag( mParameter ); |
|
return GoOn; |
|
} |
|
|
|
bool KMFilterActionAddTag::requiresBody( KMime::Content* ) const |
|
{ |
|
return false; |
|
} |
|
|
|
void KMFilterActionAddTag::argsFromString( const QString &argsStr ) |
|
{ |
|
foreach ( const QString& tag, mParameterList ) { |
|
if ( tag == argsStr ) { |
|
mParameter = tag; |
|
return; |
|
} |
|
} |
|
mParameter = mParameterList.at( 0 ); |
|
} |
|
|
|
const QString KMFilterActionAddTag::argsAsString() const |
|
{ |
|
const int idx = mParameterList.indexOf( mParameter ); |
|
if ( idx == -1 ) return QString(); |
|
|
|
return mParameterList.at( idx ); |
|
} |
|
|
|
const QString KMFilterActionAddTag::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionFakeDisposition - send fake MDN |
|
// Sends a fake MDN or forces an ignore. |
|
//============================================================================= |
|
class KMFilterActionFakeDisposition: public KMFilterActionWithStringList |
|
{ |
|
public: |
|
KMFilterActionFakeDisposition(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction() { |
|
return (new KMFilterActionFakeDisposition); |
|
} |
|
|
|
virtual bool isEmpty() const { return false; } |
|
|
|
virtual void argsFromString( const QString &argsStr ); |
|
virtual const QString argsAsString() const; |
|
virtual const QString displayString() const; |
|
}; |
|
|
|
|
|
// if you change this list, also update |
|
// the count in argsFromString |
|
static const KMime::MDN::DispositionType mdns[] = |
|
{ |
|
KMime::MDN::Displayed, |
|
KMime::MDN::Deleted, |
|
KMime::MDN::Dispatched, |
|
KMime::MDN::Processed, |
|
KMime::MDN::Denied, |
|
KMime::MDN::Failed, |
|
}; |
|
static const int numMDNs = sizeof mdns / sizeof *mdns; |
|
|
|
|
|
KMFilterActionFakeDisposition::KMFilterActionFakeDisposition() |
|
: KMFilterActionWithStringList( "fake mdn", i18n("Send Fake MDN") ) |
|
{ |
|
// if you change this list, also update |
|
// mdns above |
|
mParameterList.append( "" ); |
|
mParameterList.append( i18nc("MDN type","Ignore") ); |
|
mParameterList.append( i18nc("MDN type","Displayed") ); |
|
mParameterList.append( i18nc("MDN type","Deleted") ); |
|
mParameterList.append( i18nc("MDN type","Dispatched") ); |
|
mParameterList.append( i18nc("MDN type","Processed") ); |
|
mParameterList.append( i18nc("MDN type","Denied") ); |
|
mParameterList.append( i18nc("MDN type","Failed") ); |
|
|
|
mParameter = mParameterList.at(0); |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionFakeDisposition::process( const Akonadi::Item &item ) const |
|
{ |
|
int idx = mParameterList.indexOf( mParameter ); |
|
if ( idx < 1 ) return ErrorButGoOn; |
|
|
|
const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
if ( idx == 1 ) // ignore |
|
KMail::MessageInfo::instance()->setMDNSentState( msg.get(), KMMsgMDNIgnore ); |
|
else // send |
|
sendMDN( msg, mdns[idx-2] ); // skip first two entries: "" and "ignore" |
|
return GoOn; |
|
} |
|
|
|
void KMFilterActionFakeDisposition::argsFromString( const QString &argsStr ) |
|
{ |
|
if ( argsStr.length() == 1 ) { |
|
if ( argsStr[0] == 'I' ) { // ignore |
|
mParameter = mParameterList.at(1); |
|
return; |
|
} |
|
for ( int i = 0 ; i < numMDNs ; i++ ) |
|
if ( char(mdns[i]) == argsStr[0] ) { // send |
|
mParameter = mParameterList.at(i+2); |
|
return; |
|
} |
|
} |
|
mParameter = mParameterList.at(0); |
|
} |
|
|
|
const QString KMFilterActionFakeDisposition::argsAsString() const |
|
{ |
|
int idx = mParameterList.indexOf( mParameter ); |
|
if ( idx < 1 ) return QString(); |
|
|
|
return QString( QChar( idx < 2 ? 'I' : char(mdns[idx-2]) ) ); |
|
} |
|
|
|
const QString KMFilterActionFakeDisposition::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionRemoveHeader - remove header |
|
// Remove all instances of the given header field. |
|
//============================================================================= |
|
class KMFilterActionRemoveHeader: public KMFilterActionWithStringList |
|
{ |
|
public: |
|
KMFilterActionRemoveHeader(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual QWidget* createParamWidget( QWidget* parent ) const; |
|
virtual void setParamWidgetValue( QWidget* paramWidget ) const; |
|
|
|
static KMFilterAction* newAction(); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionRemoveHeader::newAction() |
|
{ |
|
return (new KMFilterActionRemoveHeader); |
|
} |
|
|
|
KMFilterActionRemoveHeader::KMFilterActionRemoveHeader() |
|
: KMFilterActionWithStringList( "remove header", i18n("Remove Header") ) |
|
{ |
|
mParameterList << "" |
|
<< "Reply-To" |
|
<< "Delivered-To" |
|
<< "X-KDE-PR-Message" |
|
<< "X-KDE-PR-Package" |
|
<< "X-KDE-PR-Keywords"; |
|
mParameter = mParameterList.at(0); |
|
} |
|
|
|
QWidget* KMFilterActionRemoveHeader::createParamWidget( QWidget* parent ) const |
|
{ |
|
KComboBox *cb = new KComboBox( parent ); |
|
cb->setEditable( true ); |
|
cb->setInsertPolicy( QComboBox::InsertAtBottom ); |
|
setParamWidgetValue( cb ); |
|
return cb; |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionRemoveHeader::process( const Akonadi::Item &item ) const |
|
{ |
|
if ( mParameter.isEmpty() ) return ErrorButGoOn; |
|
|
|
KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
while ( msg->headerByType( mParameter.toLatin1() ) ) |
|
msg->removeHeader( mParameter.toLatin1() ); |
|
return GoOn; |
|
} |
|
|
|
void KMFilterActionRemoveHeader::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
KComboBox * cb = dynamic_cast<KComboBox*>(paramWidget); |
|
Q_ASSERT( cb ); |
|
|
|
int idx = mParameterList.indexOf( mParameter ); |
|
cb->clear(); |
|
cb->addItems( mParameterList ); |
|
if ( idx < 0 ) { |
|
cb->addItem( mParameter ); |
|
cb->setCurrentIndex( cb->count() - 1 ); |
|
} else { |
|
cb->setCurrentIndex( idx ); |
|
} |
|
} |
|
|
|
|
|
//============================================================================= |
|
// KMFilterActionAddHeader - add header |
|
// Add a header with the given value. |
|
//============================================================================= |
|
class KMFilterActionAddHeader: public KMFilterActionWithStringList |
|
{ |
|
public: |
|
KMFilterActionAddHeader(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual QWidget* createParamWidget( QWidget* parent ) const; |
|
virtual void setParamWidgetValue( QWidget* paramWidget ) const; |
|
virtual void applyParamWidgetValue( QWidget* paramWidget ); |
|
virtual void clearParamWidget( QWidget* paramWidget ) const; |
|
|
|
virtual const QString argsAsString() const; |
|
virtual void argsFromString( const QString &argsStr ); |
|
|
|
virtual const QString displayString() const; |
|
|
|
static KMFilterAction* newAction() |
|
{ |
|
return (new KMFilterActionAddHeader); |
|
} |
|
private: |
|
QString mValue; |
|
}; |
|
|
|
KMFilterActionAddHeader::KMFilterActionAddHeader() |
|
: KMFilterActionWithStringList( "add header", i18n("Add Header") ) |
|
{ |
|
mParameterList << "" |
|
<< "Reply-To" |
|
<< "Delivered-To" |
|
<< "X-KDE-PR-Message" |
|
<< "X-KDE-PR-Package" |
|
<< "X-KDE-PR-Keywords"; |
|
mParameter = mParameterList.at(0); |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionAddHeader::process( const Akonadi::Item &item ) const |
|
{ |
|
if ( mParameter.isEmpty() ) return ErrorButGoOn; |
|
|
|
KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
KMime::Headers::Generic *header = new KMime::Headers::Generic( mParameter.toLatin1(), msg.get(), mValue, "utf-8" ); |
|
msg->setHeader( header ); |
|
return GoOn; |
|
} |
|
|
|
QWidget* KMFilterActionAddHeader::createParamWidget( QWidget* parent ) const |
|
{ |
|
QWidget *w = new QWidget( parent ); |
|
QHBoxLayout *hbl = new QHBoxLayout( w ); |
|
hbl->setSpacing( 4 ); |
|
hbl->setMargin( 0 ); |
|
KComboBox *cb = new KComboBox( w ); |
|
cb->setObjectName( "combo" ); |
|
cb->setEditable( true ); |
|
cb->setInsertPolicy( QComboBox::InsertAtBottom ); |
|
hbl->addWidget( cb, 0 /* stretch */ ); |
|
QLabel *l = new QLabel( i18n("With value:"), w ); |
|
l->setFixedWidth( l->sizeHint().width() ); |
|
hbl->addWidget( l, 0 ); |
|
KLineEdit *le = new KLineEdit( w ); |
|
le->setObjectName( "ledit" ); |
|
le->setClearButtonShown( true ); |
|
hbl->addWidget( le, 1 ); |
|
setParamWidgetValue( w ); |
|
return w; |
|
} |
|
|
|
void KMFilterActionAddHeader::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
int idx = mParameterList.indexOf( mParameter ); |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>("combo"); |
|
Q_ASSERT( cb ); |
|
cb->clear(); |
|
cb->addItems( mParameterList ); |
|
if ( idx < 0 ) { |
|
cb->addItem( mParameter ); |
|
cb->setCurrentIndex( cb->count() - 1 ); |
|
} else { |
|
cb->setCurrentIndex( idx ); |
|
} |
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>("ledit"); |
|
Q_ASSERT( le ); |
|
le->setText( mValue ); |
|
} |
|
|
|
void KMFilterActionAddHeader::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>("combo"); |
|
Q_ASSERT( cb ); |
|
mParameter = cb->currentText(); |
|
|
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>("ledit"); |
|
Q_ASSERT( le ); |
|
mValue = le->text(); |
|
} |
|
|
|
void KMFilterActionAddHeader::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>("combo"); |
|
Q_ASSERT( cb ); |
|
cb->setCurrentIndex(0); |
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>("ledit"); |
|
Q_ASSERT( le ); |
|
le->clear(); |
|
} |
|
|
|
const QString KMFilterActionAddHeader::argsAsString() const |
|
{ |
|
QString result = mParameter; |
|
result += '\t'; |
|
result += mValue; |
|
|
|
return result; |
|
} |
|
|
|
const QString KMFilterActionAddHeader::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
void KMFilterActionAddHeader::argsFromString( const QString &argsStr ) |
|
{ |
|
QStringList l = argsStr.split( '\t' ); |
|
QString s; |
|
if ( l.count() < 2 ) { |
|
s = l[0]; |
|
mValue = ""; |
|
} else { |
|
s = l[0]; |
|
mValue = l[1]; |
|
} |
|
|
|
int idx = mParameterList.indexOf( s ); |
|
if ( idx < 0 ) { |
|
mParameterList.append( s ); |
|
idx = mParameterList.count() - 1; |
|
} |
|
mParameter = mParameterList.at( idx ); |
|
} |
|
|
|
|
|
//============================================================================= |
|
// KMFilterActionRewriteHeader - rewrite header |
|
// Rewrite a header using a regexp. |
|
//============================================================================= |
|
class KMFilterActionRewriteHeader: public KMFilterActionWithStringList |
|
{ |
|
public: |
|
KMFilterActionRewriteHeader(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual QWidget* createParamWidget( QWidget* parent ) const; |
|
virtual void setParamWidgetValue( QWidget* paramWidget ) const; |
|
virtual void applyParamWidgetValue( QWidget* paramWidget ); |
|
virtual void clearParamWidget( QWidget* paramWidget ) const; |
|
|
|
virtual const QString argsAsString() const; |
|
virtual void argsFromString( const QString &argsStr ); |
|
|
|
virtual const QString displayString() const; |
|
|
|
static KMFilterAction* newAction() |
|
{ |
|
return (new KMFilterActionRewriteHeader); |
|
} |
|
private: |
|
QRegExp mRegExp; |
|
QString mReplacementString; |
|
}; |
|
|
|
KMFilterActionRewriteHeader::KMFilterActionRewriteHeader() |
|
: KMFilterActionWithStringList( "rewrite header", i18n("Rewrite Header") ) |
|
{ |
|
mParameterList << "" |
|
<< "Subject" |
|
<< "Reply-To" |
|
<< "Delivered-To" |
|
<< "X-KDE-PR-Message" |
|
<< "X-KDE-PR-Package" |
|
<< "X-KDE-PR-Keywords"; |
|
mParameter = mParameterList.at(0); |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionRewriteHeader::process( const Akonadi::Item &item ) const |
|
{ |
|
if ( mParameter.isEmpty() || !mRegExp.isValid() ) |
|
return ErrorButGoOn; |
|
|
|
const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
// QString::replace is not const. |
|
QString value = msg->headerByType( mParameter.toLatin1() ) ? msg->headerByType( mParameter.toLatin1() )->asUnicodeString(): ""; |
|
|
|
KMime::Headers::Generic *header = new KMime::Headers::Generic( mParameter.toLatin1(), msg.get(), value.replace( mRegExp, mReplacementString ), "utf-8" ); |
|
msg->setHeader( header ); |
|
|
|
return GoOn; |
|
} |
|
|
|
QWidget* KMFilterActionRewriteHeader::createParamWidget( QWidget* parent ) const |
|
{ |
|
QWidget *w = new QWidget( parent ); |
|
QHBoxLayout *hbl = new QHBoxLayout( w ); |
|
hbl->setSpacing( 4 ); |
|
hbl->setMargin( 0 ); |
|
|
|
KComboBox *cb = new KComboBox( w ); |
|
cb->setEditable( true ); |
|
cb->setObjectName( "combo" ); |
|
cb->setInsertPolicy( QComboBox::InsertAtBottom ); |
|
hbl->addWidget( cb, 0 /* stretch */ ); |
|
|
|
QLabel *l = new QLabel( i18n("Replace:"), w ); |
|
l->setFixedWidth( l->sizeHint().width() ); |
|
hbl->addWidget( l, 0 ); |
|
|
|
RegExpLineEdit *rele = new RegExpLineEdit( w ); |
|
rele->setObjectName( "search" ); |
|
hbl->addWidget( rele, 1 ); |
|
|
|
l = new QLabel( i18n("With:"), w ); |
|
l->setFixedWidth( l->sizeHint().width() ); |
|
hbl->addWidget( l, 0 ); |
|
|
|
KLineEdit *le = new KLineEdit( w ); |
|
le->setObjectName( "replace" ); |
|
le->setClearButtonShown( true ); |
|
hbl->addWidget( le, 1 ); |
|
|
|
setParamWidgetValue( w ); |
|
return w; |
|
} |
|
|
|
void KMFilterActionRewriteHeader::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
int idx = mParameterList.indexOf( mParameter ); |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>("combo"); |
|
Q_ASSERT( cb ); |
|
|
|
cb->clear(); |
|
cb->addItems( mParameterList ); |
|
if ( idx < 0 ) { |
|
cb->addItem( mParameter ); |
|
cb->setCurrentIndex( cb->count() - 1 ); |
|
} else { |
|
cb->setCurrentIndex( idx ); |
|
} |
|
|
|
RegExpLineEdit *rele = paramWidget->findChild<RegExpLineEdit*>("search"); |
|
Q_ASSERT( rele ); |
|
rele->setText( mRegExp.pattern() ); |
|
|
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>("replace"); |
|
Q_ASSERT( le ); |
|
le->setText( mReplacementString ); |
|
} |
|
|
|
void KMFilterActionRewriteHeader::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>("combo"); |
|
Q_ASSERT( cb ); |
|
mParameter = cb->currentText(); |
|
|
|
RegExpLineEdit *rele = paramWidget->findChild<RegExpLineEdit*>("search"); |
|
Q_ASSERT( rele ); |
|
mRegExp.setPattern( rele->text() ); |
|
|
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>("replace"); |
|
Q_ASSERT( le ); |
|
mReplacementString = le->text(); |
|
} |
|
|
|
void KMFilterActionRewriteHeader::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>("combo"); |
|
Q_ASSERT( cb ); |
|
cb->setCurrentIndex(0); |
|
|
|
RegExpLineEdit *rele = paramWidget->findChild<RegExpLineEdit*>("search"); |
|
Q_ASSERT( rele ); |
|
rele->clear(); |
|
|
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>("replace"); |
|
Q_ASSERT( le ); |
|
le->clear(); |
|
} |
|
|
|
const QString KMFilterActionRewriteHeader::argsAsString() const |
|
{ |
|
QString result = mParameter; |
|
result += '\t'; |
|
result += mRegExp.pattern(); |
|
result += '\t'; |
|
result += mReplacementString; |
|
|
|
return result; |
|
} |
|
|
|
const QString KMFilterActionRewriteHeader::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
void KMFilterActionRewriteHeader::argsFromString( const QString &argsStr ) |
|
{ |
|
QStringList l = argsStr.split( '\t' ); |
|
QString s; |
|
|
|
s = l[0]; |
|
mRegExp.setPattern( l[1] ); |
|
mReplacementString = l[2]; |
|
|
|
int idx = mParameterList.indexOf( s ); |
|
if ( idx < 0 ) { |
|
mParameterList.append( s ); |
|
idx = mParameterList.count() - 1; |
|
} |
|
mParameter = mParameterList.at( idx ); |
|
} |
|
|
|
|
|
//============================================================================= |
|
// KMFilterActionMove - move into folder |
|
// File message into another mail folder |
|
//============================================================================= |
|
class KMFilterActionMove: public KMFilterActionWithFolder |
|
{ |
|
public: |
|
KMFilterActionMove(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual bool requiresBody(KMime::Content*) const; |
|
static KMFilterAction* newAction(void); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionMove::newAction(void) |
|
{ |
|
return (new KMFilterActionMove); |
|
} |
|
|
|
KMFilterActionMove::KMFilterActionMove() |
|
: KMFilterActionWithFolder( "transfer", i18n("Move Into Folder") ) |
|
{ |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionMove::process( const Akonadi::Item &item ) const |
|
{ |
|
if ( !mFolder.isValid() ) |
|
return ErrorButGoOn; |
|
MessageProperty::setFilterFolder( item, mFolder ); |
|
return GoOn; |
|
} |
|
|
|
bool KMFilterActionMove::requiresBody(KMime::Content*) const |
|
{ |
|
return false; //iff mFolder->folderMgr == msgBase->parent()->folderMgr; |
|
} |
|
|
|
|
|
//============================================================================= |
|
// KMFilterActionCopy - copy into folder |
|
// Copy message into another mail folder |
|
//============================================================================= |
|
class KMFilterActionCopy: public KMFilterActionWithFolder |
|
{ |
|
public: |
|
KMFilterActionCopy(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual void processAsync( const Akonadi::Item &item ) const; |
|
virtual bool requiresBody( KMime::Content *) const; |
|
static KMFilterAction* newAction(void); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionCopy::newAction( void ) |
|
{ |
|
return ( new KMFilterActionCopy ); |
|
} |
|
|
|
KMFilterActionCopy::KMFilterActionCopy() |
|
: KMFilterActionWithFolder( "copy", i18n("Copy Into Folder") ) |
|
{ |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionCopy::process( const Akonadi::Item &item ) const |
|
{ |
|
// copy the message 1:1 |
|
new Akonadi::ItemCopyJob( item, mFolder, kmkernel->filterMgr() ); // TODO handle error |
|
return GoOn; |
|
} |
|
|
|
void KMFilterActionCopy::processAsync( const Akonadi::Item &item ) const |
|
{ |
|
ActionScheduler *handler = MessageProperty::filterHandler( item ); |
|
|
|
KMCommand *cmd = new KMCopyCommand( mFolder, item ); |
|
QObject::connect( cmd, SIGNAL( completed( KMCommand * ) ), |
|
handler, SLOT( copyMessageFinished( KMCommand * ) ) ); |
|
cmd->start(); |
|
} |
|
|
|
bool KMFilterActionCopy::requiresBody( KMime::Content *msg ) const |
|
{ |
|
Q_UNUSED( msg ); |
|
return true; |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionForward - forward to |
|
// Forward message to another user, with a defined template |
|
//============================================================================= |
|
class KMFilterActionForward: public KMFilterActionWithAddress |
|
{ |
|
public: |
|
KMFilterActionForward(); |
|
static KMFilterAction* newAction( void ); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual QWidget* createParamWidget( QWidget* parent ) const; |
|
virtual void applyParamWidgetValue( QWidget* paramWidget ); |
|
virtual void setParamWidgetValue( QWidget* paramWidget ) const; |
|
virtual void clearParamWidget( QWidget* paramWidget ) const; |
|
virtual void argsFromString( const QString &argsStr ); |
|
virtual const QString argsAsString() const; |
|
virtual const QString displayString() const; |
|
|
|
private: |
|
|
|
mutable QString mTemplate; |
|
}; |
|
|
|
KMFilterAction *KMFilterActionForward::newAction( void ) |
|
{ |
|
return ( new KMFilterActionForward ); |
|
} |
|
|
|
KMFilterActionForward::KMFilterActionForward() |
|
: KMFilterActionWithAddress( "forward", i18n("Forward To") ) |
|
{ |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionForward::process( const Akonadi::Item &item ) const |
|
{ |
|
if ( mParameter.isEmpty() ) |
|
return ErrorButGoOn; |
|
|
|
const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
// avoid endless loops when this action is used in a filter |
|
// which applies to sent messages |
|
if ( MessageViewer::StringUtil::addressIsInAddressList( mParameter, QStringList( msg->to()->asUnicodeString() ) ) ) { |
|
kWarning() << "Attempt to forward to receipient of original message, ignoring."; |
|
return ErrorButGoOn; |
|
} |
|
|
|
KMime::Message::Ptr fwdMsg = KMail::MessageHelper::createForward( item, msg, mTemplate ); |
|
fwdMsg->to()->fromUnicodeString( fwdMsg->to()->asUnicodeString() + ',' + mParameter, "utf-8" ); |
|
if ( !kmkernel->msgSender()->send( fwdMsg, KMail::MessageSender::SendDefault ) ) { |
|
kWarning() << "KMFilterAction: could not forward message (sending failed)"; |
|
return ErrorButGoOn; // error: couldn't send |
|
} |
|
else |
|
sendMDN( msg, KMime::MDN::Dispatched ); |
|
|
|
// (the msgSender takes ownership of the message, so don't delete it here) |
|
return GoOn; |
|
} |
|
|
|
QWidget* KMFilterActionForward::createParamWidget( QWidget* parent ) const |
|
{ |
|
QWidget *addressAndTemplate = new QWidget( parent ); |
|
QHBoxLayout *hBox = new QHBoxLayout( addressAndTemplate ); |
|
hBox->setMargin( 0 ); |
|
QWidget *addressEdit = KMFilterActionWithAddress::createParamWidget( addressAndTemplate ); |
|
addressEdit->setObjectName( "addressEdit" ); |
|
hBox->addWidget( addressEdit ); |
|
|
|
KLineEdit *lineEdit = addressEdit->findChild<KLineEdit*>( "addressEdit" ); |
|
Q_ASSERT( lineEdit ); |
|
lineEdit->setToolTip( i18n( "The addressee to whom the message will be forwarded." ) ); |
|
lineEdit->setWhatsThis( i18n( "The filter will forward the message to the addressee entered here." ) ); |
|
|
|
KComboBox *templateCombo = new KComboBox( addressAndTemplate ); |
|
templateCombo->setObjectName( "templateCombo" ); |
|
hBox->addWidget( templateCombo ); |
|
|
|
templateCombo->addItem( i18n( "Default Template" ) ); |
|
QStringList templateNames = GlobalSettingsBase::self()->customTemplates(); |
|
foreach( const QString &templateName, templateNames ) { |
|
CTemplates templat( templateName ); |
|
if ( templat.type() == CustomTemplates::TForward || |
|
templat.type() == CustomTemplates::TUniversal ) |
|
templateCombo->addItem( templateName ); |
|
} |
|
templateCombo->setEnabled( templateCombo->count() > 1 ); |
|
templateCombo->setToolTip( i18n( "The template used when forwarding" ) ); |
|
templateCombo->setWhatsThis( i18n( "Set the forwarding template that will be used with this filter." ) ); |
|
|
|
return addressAndTemplate; |
|
} |
|
|
|
void KMFilterActionForward::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
QWidget *addressEdit = paramWidget->findChild<QWidget*>( "addressEdit" ); |
|
Q_ASSERT( addressEdit ); |
|
KMFilterActionWithAddress::applyParamWidgetValue( addressEdit ); |
|
|
|
KComboBox *templateCombo = paramWidget->findChild<KComboBox*>( "templateCombo" ); |
|
Q_ASSERT( templateCombo ); |
|
|
|
if ( templateCombo->currentIndex() == 0 ) { |
|
// Default template, so don't use a custom one |
|
mTemplate.clear(); |
|
} |
|
else { |
|
mTemplate = templateCombo->currentText(); |
|
} |
|
} |
|
|
|
void KMFilterActionForward::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
QWidget *addressEdit = paramWidget->findChild<QWidget*>( "addressEdit" ); |
|
Q_ASSERT( addressEdit ); |
|
KMFilterActionWithAddress::setParamWidgetValue( addressEdit ); |
|
|
|
KComboBox *templateCombo = paramWidget->findChild<KComboBox*>( "templateCombo" ); |
|
Q_ASSERT( templateCombo ); |
|
|
|
if ( mTemplate.isEmpty() ) { |
|
templateCombo->setCurrentIndex( 0 ); |
|
} |
|
else { |
|
int templateIndex = templateCombo->findText( mTemplate ); |
|
if ( templateIndex != -1 ) { |
|
templateCombo->setCurrentIndex( templateIndex ); |
|
} |
|
else { |
|
mTemplate.clear(); |
|
} |
|
} |
|
} |
|
|
|
void KMFilterActionForward::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
QWidget *addressEdit = paramWidget->findChild<QWidget*>( "addressEdit" ); |
|
Q_ASSERT( addressEdit ); |
|
KMFilterActionWithAddress::clearParamWidget( addressEdit ); |
|
|
|
KComboBox *templateCombo = paramWidget->findChild<KComboBox*>( "templateCombo" ); |
|
Q_ASSERT( templateCombo ); |
|
|
|
templateCombo->setCurrentIndex( 0 ); |
|
} |
|
|
|
// We simply place a "@$$@" between the two parameters. The template is the last |
|
// parameter in the string, for compatibility reasons. |
|
static const QString forwardFilterArgsSeperator = "@$$@"; |
|
|
|
void KMFilterActionForward::argsFromString( const QString &argsStr ) |
|
{ |
|
int seperatorPos = argsStr.indexOf( forwardFilterArgsSeperator ); |
|
|
|
if ( seperatorPos == - 1 ) { |
|
// Old config, assume that the whole string is the addressee |
|
KMFilterActionWithAddress::argsFromString( argsStr ); |
|
} |
|
else { |
|
QString addressee = argsStr.left( seperatorPos ); |
|
mTemplate = argsStr.mid( seperatorPos + forwardFilterArgsSeperator.length() ); |
|
KMFilterActionWithAddress::argsFromString( addressee ); |
|
} |
|
} |
|
|
|
const QString KMFilterActionForward::argsAsString() const |
|
{ |
|
return KMFilterActionWithAddress::argsAsString() + forwardFilterArgsSeperator + mTemplate; |
|
} |
|
|
|
const QString KMFilterActionForward::displayString() const |
|
{ |
|
if ( mTemplate.isEmpty() ) |
|
return i18n( "Forward to %1 with default template", mParameter ); |
|
else |
|
return i18n( "Forward to %1 with template %2", mParameter, mTemplate ); |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionRedirect - redirect to |
|
// Redirect message to another user |
|
//============================================================================= |
|
class KMFilterActionRedirect: public KMFilterActionWithAddress |
|
{ |
|
public: |
|
KMFilterActionRedirect(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction(void); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionRedirect::newAction(void) |
|
{ |
|
return (new KMFilterActionRedirect); |
|
} |
|
|
|
KMFilterActionRedirect::KMFilterActionRedirect() |
|
: KMFilterActionWithAddress( "redirect", i18n("Redirect To") ) |
|
{ |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionRedirect::process( const Akonadi::Item &item ) const |
|
{ |
|
if ( mParameter.isEmpty() ) |
|
return ErrorButGoOn; |
|
|
|
KMime::Message::Ptr msg = KMail::MessageHelper::createRedirect( item, mParameter ); |
|
if ( !msg ) |
|
return ErrorButGoOn; |
|
|
|
sendMDN( KMail::Util::message( item ), KMime::MDN::Dispatched ); |
|
|
|
if ( !kmkernel->msgSender()->send( msg, KMail::MessageSender::SendLater ) ) { |
|
kDebug() << "KMFilterAction: could not redirect message (sending failed)"; |
|
return ErrorButGoOn; // error: couldn't send |
|
} |
|
return GoOn; |
|
} |
|
|
|
|
|
//============================================================================= |
|
// KMFilterActionExec - execute command |
|
// Execute a shell command |
|
//============================================================================= |
|
class KMFilterActionExec : public KMFilterActionWithCommand |
|
{ |
|
public: |
|
KMFilterActionExec(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction(void); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionExec::newAction(void) |
|
{ |
|
return (new KMFilterActionExec()); |
|
} |
|
|
|
KMFilterActionExec::KMFilterActionExec() |
|
: KMFilterActionWithCommand( "execute", i18n("Execute Command") ) |
|
{ |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionExec::process( const Akonadi::Item &item ) const |
|
{ |
|
return KMFilterActionWithCommand::genericProcess( item, false ); // ignore output |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionExtFilter - use external filter app |
|
// External message filter: executes a shell command with message |
|
// on stdin; altered message is expected on stdout. |
|
//============================================================================= |
|
|
|
#include <threadweaver/ThreadWeaver.h> |
|
#include <threadweaver/Job.h> |
|
#include <threadweaver/DebuggingAids.h> |
|
class PipeJob : public ThreadWeaver::Job |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
PipeJob(QObject* parent = 0, const KMime::Message::Ptr &aMsg = KMime::Message::Ptr(), |
|
QString cmd = 0, QString tempFileName = 0 ) |
|
: ThreadWeaver::Job ( parent ), |
|
mTempFileName( tempFileName ), |
|
mCmd( cmd ), |
|
mMsg( aMsg ) |
|
{ |
|
connect( this, SIGNAL( done( ThreadWeaver::Job* ) ), |
|
this, SLOT( slotDone( ThreadWeaver::Job* ) ) ); |
|
} |
|
|
|
~PipeJob() {} |
|
|
|
private slots: |
|
|
|
void slotDone( ThreadWeaver::Job * ) |
|
{ |
|
deleteLater( ); |
|
} |
|
|
|
protected: |
|
|
|
virtual void run() |
|
{ |
|
ThreadWeaver::debug (1, "PipeJob::run: doing it .\n"); |
|
FILE *p; |
|
QByteArray ba; |
|
|
|
// backup the serial number in case the header gets lost |
|
QString origSerNum = mMsg->headerByType( "X-KMail-Filtered" ) ? mMsg->headerByType( "X-KMail-Filtered" )->asUnicodeString() : ""; |
|
|
|
p = popen(QFile::encodeName(mCmd), "r"); |
|
int len =100; |
|
char buffer[100]; |
|
// append data to ba: |
|
while (true) { |
|
if (! fgets( buffer, len, p ) ) break; |
|
int oldsize = ba.size(); |
|
ba.resize( oldsize + strlen(buffer) ); |
|
memmove( ba.begin() + oldsize, buffer, strlen(buffer) ); |
|
} |
|
pclose(p); |
|
if ( !ba.isEmpty() ) { |
|
#if 0 //TODO port to akonadi |
|
ThreadWeaver::debug (1, "PipeJob::run: %s", ba.constData() ); |
|
KMFolder *filterFolder = mMsg->parent(); |
|
ActionScheduler *handler = MessageProperty::filterHandler( mMsg->getMsgSerNum() ); |
|
|
|
// If the pipe through alters the message, it could very well |
|
// happen that it no longer has a X-UID header afterwards. That is |
|
// unfortunate, as we need to removed the original from the folder |
|
// using that, and look it up in the message. When the (new) message |
|
// is uploaded, the header is stripped anyhow. */ |
|
const QString uid = mMsg->headerField( "X-UID", KMime::Message::NoEncoding ); |
|
mMsg->fromString( ba ); |
|
if ( !uid.isEmpty() ) |
|
mMsg->setHeaderField( "X-UID", uid, KMime::Message::Unstructured, false, KMime::Message::NoEncoding ); |
|
|
|
if ( !origSerNum.isEmpty() ) |
|
mMsg->setHeaderField( "X-KMail-Filtered", origSerNum ); |
|
if ( filterFolder && handler ) { |
|
handler->addMsgToIgnored( mMsg->getMsgSerNum() ); |
|
filterFolder->take( filterFolder->find( mMsg ) ); |
|
filterFolder->addMsg( mMsg ); |
|
} else { |
|
kDebug() << "Warning: Cannot refresh the message from the external filter."; |
|
} |
|
#else |
|
kDebug() << "AKONADI PORT: Disabled code in " << Q_FUNC_INFO; |
|
#endif |
|
} |
|
|
|
ThreadWeaver::debug (1, "PipeJob::run: done.\n" ); |
|
// unlink the tempFile |
|
QFile::remove(mTempFileName); |
|
} |
|
|
|
QString mTempFileName; |
|
QString mCmd; |
|
KMime::Message::Ptr mMsg; |
|
}; |
|
|
|
class KMFilterActionExtFilter: public KMFilterActionWithCommand |
|
{ |
|
public: |
|
KMFilterActionExtFilter(); |
|
virtual ReturnCode process( const Akonadi::Item &item2 ) const; |
|
virtual void processAsync( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction(void); |
|
}; |
|
|
|
KMFilterAction* KMFilterActionExtFilter::newAction(void) |
|
{ |
|
return (new KMFilterActionExtFilter); |
|
} |
|
|
|
KMFilterActionExtFilter::KMFilterActionExtFilter() |
|
: KMFilterActionWithCommand( "filter app", i18n("Pipe Through") ) |
|
{ |
|
} |
|
KMFilterAction::ReturnCode KMFilterActionExtFilter::process( const Akonadi::Item &item ) const |
|
{ |
|
return KMFilterActionWithCommand::genericProcess( item, true ); // use output |
|
} |
|
|
|
void KMFilterActionExtFilter::processAsync( const Akonadi::Item &item ) const |
|
{ |
|
ActionScheduler *handler = MessageProperty::filterHandler( item ); |
|
KTemporaryFile *inFile = new KTemporaryFile; |
|
inFile->setAutoRemove(false); |
|
if ( !inFile->open() ) { |
|
delete inFile; |
|
handler->actionMessage( ErrorButGoOn ); |
|
return; |
|
} |
|
|
|
QList<KTemporaryFile*> atmList; |
|
atmList.append( inFile ); |
|
|
|
#if 0 //TODO port to akonadi |
|
QString commandLine = substituteCommandLineArgsFor( aMsg, atmList ); |
|
if ( commandLine.isEmpty() ) { |
|
handler->actionMessage( ErrorButGoOn ); |
|
qDeleteAll( atmList ); |
|
atmList.clear(); |
|
return; |
|
} |
|
|
|
// The parentheses force the creation of a subshell |
|
// in which the user-specified command is executed. |
|
// This is to really catch all output of the command as well |
|
// as to avoid clashes of our redirection with the ones |
|
// the user may have specified. In the long run, we |
|
// shouldn't be using tempfiles at all for this class, due |
|
// to security aspects. (mmutz) |
|
commandLine = '(' + commandLine + ") <" + inFile->fileName(); |
|
|
|
// write message to file |
|
QString tempFileName = inFile->fileName(); |
|
if ( !KPIMUtils::kByteArrayToFile( aMsg->asString(), tempFileName, //### |
|
false, false, false ) ) { |
|
handler->actionMessage( CriticalError ); |
|
qDeleteAll( atmList ); |
|
atmList.clear(); |
|
return; |
|
} |
|
|
|
inFile->close(); |
|
qDeleteAll( atmList ); |
|
atmList.clear(); |
|
|
|
PipeJob *job = new PipeJob(0, aMsg, commandLine, tempFileName); |
|
QObject::connect ( job, SIGNAL( done( ThreadWeaver::Job* ) ), |
|
handler, SLOT( actionMessage() ) ); |
|
kmkernel->weaver()->enqueue(job); |
|
#else |
|
kDebug() << "AKONADI PORT: Disabled code in " << Q_FUNC_INFO; |
|
#endif |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionExecSound - execute command |
|
// Execute a sound |
|
//============================================================================= |
|
class KMFilterActionExecSound : public KMFilterActionWithTest |
|
{ |
|
public: |
|
KMFilterActionExecSound(); |
|
~KMFilterActionExecSound(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
virtual bool requiresBody(KMime::Content*) const; |
|
static KMFilterAction* newAction(void); |
|
private: |
|
mutable Phonon::MediaObject* mPlayer; |
|
}; |
|
|
|
KMFilterActionWithTest::KMFilterActionWithTest( const char* aName, const QString &aLabel ) |
|
: KMFilterAction( aName, aLabel ) |
|
{ |
|
} |
|
|
|
KMFilterActionWithTest::~KMFilterActionWithTest() |
|
{ |
|
} |
|
|
|
QWidget* KMFilterActionWithTest::createParamWidget( QWidget* parent ) const |
|
{ |
|
KMSoundTestWidget *le = new KMSoundTestWidget(parent); |
|
le->setUrl( mParameter ); |
|
return le; |
|
} |
|
|
|
|
|
void KMFilterActionWithTest::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
mParameter = ((KMSoundTestWidget*)paramWidget)->url(); |
|
} |
|
|
|
void KMFilterActionWithTest::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
((KMSoundTestWidget*)paramWidget)->setUrl( mParameter ); |
|
} |
|
|
|
void KMFilterActionWithTest::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
((KMSoundTestWidget*)paramWidget)->clear(); |
|
} |
|
|
|
void KMFilterActionWithTest::argsFromString( const QString &argsStr ) |
|
{ |
|
mParameter = argsStr; |
|
} |
|
|
|
const QString KMFilterActionWithTest::argsAsString() const |
|
{ |
|
return mParameter; |
|
} |
|
|
|
const QString KMFilterActionWithTest::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
|
|
KMFilterActionExecSound::KMFilterActionExecSound() |
|
: KMFilterActionWithTest( "play sound", i18n("Play Sound") ), |
|
mPlayer(0) |
|
{ |
|
} |
|
|
|
KMFilterActionExecSound::~KMFilterActionExecSound() |
|
{ |
|
delete mPlayer; |
|
} |
|
|
|
KMFilterAction* KMFilterActionExecSound::newAction(void) |
|
{ |
|
return (new KMFilterActionExecSound()); |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionExecSound::process( const Akonadi::Item& ) const |
|
{ |
|
if ( mParameter.isEmpty() ) |
|
return ErrorButGoOn; |
|
|
|
if ( !mPlayer ) |
|
mPlayer = Phonon::createPlayer(Phonon::NotificationCategory); |
|
|
|
mPlayer->setCurrentSource( mParameter ); |
|
mPlayer->play(); |
|
return GoOn; |
|
} |
|
|
|
bool KMFilterActionExecSound::requiresBody(KMime::Content*) const |
|
{ |
|
return false; |
|
} |
|
|
|
KMFilterActionWithUrl::KMFilterActionWithUrl( const char* aName, const QString &aLabel ) |
|
: KMFilterAction( aName, aLabel ) |
|
{ |
|
} |
|
|
|
KMFilterActionWithUrl::~KMFilterActionWithUrl() |
|
{ |
|
} |
|
|
|
QWidget* KMFilterActionWithUrl::createParamWidget( QWidget* parent ) const |
|
{ |
|
KUrlRequester *le = new KUrlRequester(parent); |
|
le->setUrl( KUrl( mParameter ) ); |
|
return le; |
|
} |
|
|
|
|
|
void KMFilterActionWithUrl::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
const KUrl url = ((KUrlRequester*)paramWidget)->url(); |
|
mParameter = url.isLocalFile() ? url.toLocalFile() : url.path(); |
|
} |
|
|
|
void KMFilterActionWithUrl::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
((KUrlRequester*)paramWidget)->setUrl( KUrl( mParameter ) ); |
|
} |
|
|
|
void KMFilterActionWithUrl::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
((KUrlRequester*)paramWidget)->clear(); |
|
} |
|
|
|
void KMFilterActionWithUrl::argsFromString( const QString &argsStr ) |
|
{ |
|
mParameter = argsStr; |
|
} |
|
|
|
const QString KMFilterActionWithUrl::argsAsString() const |
|
{ |
|
return mParameter; |
|
} |
|
|
|
const QString KMFilterActionWithUrl::displayString() const |
|
{ |
|
return label() + " \"" + Qt::escape( argsAsString() ) + "\""; |
|
} |
|
|
|
//============================================================================= |
|
// KMFilterActionAddToAddressBook |
|
// - add email address from header to address book |
|
//============================================================================= |
|
class KMFilterActionAddToAddressBook: public KMFilterActionWithStringList |
|
{ |
|
public: |
|
KMFilterActionAddToAddressBook(); |
|
virtual ReturnCode process( const Akonadi::Item &item ) const; |
|
static KMFilterAction* newAction(); |
|
|
|
virtual bool isEmpty() const { return false; } |
|
|
|
virtual QWidget* createParamWidget( QWidget* parent ) const; |
|
virtual void setParamWidgetValue( QWidget* paramWidget ) const; |
|
virtual void applyParamWidgetValue( QWidget* paramWidget ); |
|
virtual void clearParamWidget( QWidget* paramWidget ) const; |
|
|
|
virtual const QString argsAsString() const; |
|
virtual void argsFromString( const QString &argsStr ); |
|
|
|
private: |
|
void updateResourceMaps( bool force = true ) const; |
|
QString mCategory, mResourceName; |
|
mutable QMap<QString, KABC::Resource*> mResourceByName, mResourceByID; |
|
const QString mStdResourceStr, mFromStr, mToStr, mCCStr, mBCCStr; |
|
mutable bool mResourceMapsInitalized; |
|
}; |
|
|
|
KMFilterAction* KMFilterActionAddToAddressBook::newAction() |
|
{ |
|
return ( new KMFilterActionAddToAddressBook ); |
|
} |
|
|
|
KMFilterActionAddToAddressBook::KMFilterActionAddToAddressBook() |
|
: KMFilterActionWithStringList( "add to address book", i18n( "Add to Address Book" ) ), |
|
mStdResourceStr( i18n( "<placeholder>Default</placeholder>" ) ), mFromStr( i18nc( "Email sender", "From" ) ), |
|
mToStr( i18nc( "Email recipient", "To" ) ), mCCStr( i18n( "CC" ) ), mBCCStr( i18n( "BCC" ) ), |
|
mResourceMapsInitalized( false ) |
|
{ |
|
mParameterList.append( mFromStr ); |
|
mParameterList.append( mToStr ); |
|
mParameterList.append( mCCStr ); |
|
mParameterList.append( mBCCStr ); |
|
|
|
mParameter = mParameterList.at( 0 ); |
|
|
|
mResourceName = mStdResourceStr; |
|
mCategory = i18n( "KMail Filter" ); |
|
} |
|
|
|
void KMFilterActionAddToAddressBook::updateResourceMaps( bool force ) const |
|
{ |
|
if ( force ) |
|
mResourceMapsInitalized = false; |
|
|
|
if ( mResourceMapsInitalized ) |
|
return; |
|
|
|
//find resources in standard addressbook |
|
//and prepare lookups |
|
mResourceByID.clear(); |
|
mResourceByName.clear(); |
|
|
|
const QList<KABC::Resource*> list = KABC::StdAddressBook::self()->resources(); |
|
foreach( KABC::Resource* const res, list ) { |
|
if ( !res->readOnly() && res->isOpen() ) { |
|
mResourceByID.insert( res->identifier(), res ); |
|
mResourceByName.insert( res->resourceName(), res ); |
|
} |
|
} |
|
|
|
mResourceMapsInitalized = true; |
|
} |
|
|
|
KMFilterAction::ReturnCode KMFilterActionAddToAddressBook::process( const Akonadi::Item &item ) const |
|
{ |
|
const KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>(); |
|
QString headerLine; |
|
if ( mParameter == mFromStr ) |
|
headerLine = msg->from()->asUnicodeString(); |
|
else if ( mParameter == mToStr ) |
|
headerLine = msg->to()->asUnicodeString(); |
|
else if ( mParameter == mCCStr ) |
|
headerLine = msg->cc()->asUnicodeString(); |
|
else if ( mParameter == mBCCStr ) |
|
headerLine = msg->bcc()->asUnicodeString(); |
|
|
|
const QStringList emails = KPIMUtils::splitAddressList( headerLine ); |
|
|
|
KABC::AddressBook *ab = KABC::StdAddressBook::self(); |
|
// force a reload of the address book file so that changes that were made |
|
// by other programs are loaded |
|
ab->load(); |
|
|
|
// We update the resource maps here, and not in the constructor, since that could create D-Bus |
|
// lockups when using IMAP addressbooks |
|
updateResourceMaps( false /* don't force reload */ ); |
|
|
|
QString email; |
|
QString name; |
|
|
|
QMap<QString, KABC::Resource*>::const_iterator it = mResourceByName.constFind( mResourceName ); |
|
KABC::Resource* res = 0; |
|
//if it==end(), then the resouce has been removed from addressbook |
|
//or default has been selected, in either case store in default resource |
|
if ( it != mResourceByName.constEnd() ) |
|
res = it.value(); |
|
|
|
KABC::Ticket *ticket = ab->requestSaveTicket( res ); |
|
|
|
if ( ticket ) { |
|
foreach ( const QString singleEmail, emails ) { |
|
KABC::Addressee::parseEmailAddress( singleEmail, name, email ); |
|
KABC::Addressee::List addressees = ab->findByEmail( email ); |
|
|
|
if ( addressees.isEmpty() ) { |
|
KABC::Addressee a; |
|
a.setNameFromString( name ); |
|
a.insertEmail( email, true ); |
|
if ( !mCategory.isEmpty() ) |
|
a.insertCategory( mCategory ); |
|
if ( res ) |
|
a.setResource( res ); |
|
|
|
ab->insertAddressee( a ); |
|
} |
|
} |
|
|
|
if ( !ab->save( ticket ) ) { |
|
ab->error( i18n( "Cannot save new addresses to address book." ) ); |
|
return ErrorButGoOn; |
|
} |
|
} else { |
|
ab->error( i18n( "Cannot save to address book: address book is locked." ) ); |
|
return ErrorButGoOn; |
|
} |
|
|
|
return GoOn; |
|
} |
|
|
|
QWidget* KMFilterActionAddToAddressBook::createParamWidget( QWidget* parent ) const |
|
{ |
|
QWidget *w = new QWidget( parent ); |
|
QGridLayout *gridlayout = new QGridLayout ( w ); |
|
|
|
KComboBox *cb = new KComboBox( w ); |
|
cb->setObjectName( "FilterTargetCombo" ); |
|
cb->setInsertPolicy( QComboBox::InsertAtBottom ); |
|
gridlayout->addWidget( cb, 0, 0, 2, 1, Qt::AlignVCenter ); |
|
|
|
QLabel *l = new QLabel( i18n( "with category" ), w ); |
|
gridlayout->addWidget( l, 0, 1 ); |
|
|
|
KLineEdit *le = new KLineEdit( w ); |
|
le->setObjectName( "ledit" ); |
|
gridlayout->addWidget( le, 0, 2 ); |
|
|
|
l = new QLabel( i18n( "in address book" ), w ); |
|
gridlayout->addWidget( l, 1, 1 ); |
|
|
|
KComboBox *cbAdressBook = new KComboBox( w ); |
|
cbAdressBook->setObjectName( "AddressBookCombo" ); |
|
cbAdressBook->setToolTip( i18n( "<p>This defines the preferred address book.<br />" |
|
"If it is not accessible, the filter will fallback to the default address book.</p>" ) ); |
|
cbAdressBook->setInsertPolicy( QComboBox::InsertAtBottom ); |
|
gridlayout->addWidget( cbAdressBook, 1, 2 ); |
|
|
|
setParamWidgetValue( w ); |
|
return w; |
|
} |
|
|
|
void KMFilterActionAddToAddressBook::setParamWidgetValue( QWidget* paramWidget ) const |
|
{ |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>( "FilterTargetCombo" ); |
|
Q_ASSERT( cb ); |
|
cb->clear(); |
|
cb->addItems( mParameterList ); |
|
int idx = mParameterList.indexOf( mParameter ); |
|
if ( idx < 0 ) { |
|
kDebug() << "unknown mParameter. strange???"; |
|
cb->addItem( mParameter ); |
|
cb->setCurrentIndex( cb->count() - 1 ); |
|
} else { |
|
cb->setCurrentIndex( idx ); |
|
} |
|
|
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>( "ledit" ); |
|
Q_ASSERT( le ); |
|
le->setText( mCategory ); |
|
|
|
QStringList list = mResourceByName.keys(); |
|
idx = list.indexOf( mResourceName ); |
|
KComboBox *cbAdressBook = paramWidget->findChild<KComboBox*>( "AddressBookCombo" ); |
|
Q_ASSERT( cbAdressBook ); |
|
cbAdressBook->clear(); |
|
cbAdressBook->addItem( mStdResourceStr ); |
|
cbAdressBook->addItems( mResourceByName.keys() ); |
|
if ( idx < 0 ) { |
|
cbAdressBook->setCurrentIndex( 0 ); |
|
} else { |
|
cbAdressBook->setCurrentIndex( idx + 1 /*mStdResourceStr is not in keys() */ ); |
|
} |
|
} |
|
|
|
void KMFilterActionAddToAddressBook::applyParamWidgetValue( QWidget* paramWidget ) |
|
{ |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>( "FilterTargetCombo" ); |
|
Q_ASSERT( cb ); |
|
mParameter = cb->currentText(); |
|
|
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>( "ledit" ); |
|
Q_ASSERT( le ); |
|
mCategory = le->text(); |
|
|
|
KComboBox *cbAdressBook = paramWidget->findChild<KComboBox*>( "AddressBookCombo" ); |
|
Q_ASSERT( cbAdressBook ); |
|
mResourceName = cbAdressBook->currentText(); |
|
} |
|
|
|
void KMFilterActionAddToAddressBook::clearParamWidget( QWidget* paramWidget ) const |
|
{ |
|
KComboBox *cb = paramWidget->findChild<KComboBox*>( "FilterTargetCombo" ); |
|
Q_ASSERT( cb ); |
|
cb->setCurrentItem( 0 ); |
|
KLineEdit *le = paramWidget->findChild<KLineEdit*>( "ledit" ); |
|
Q_ASSERT( le ); |
|
le->setText( mCategory ); |
|
KComboBox *cbAdressBook = paramWidget->findChild<KComboBox*>( "AddressBookCombo" ); |
|
Q_ASSERT( cbAdressBook ); |
|
cbAdressBook->setCurrentItem( 0 ); |
|
} |
|
|
|
const QString KMFilterActionAddToAddressBook::argsAsString() const |
|
{ |
|
QString result; |
|
|
|
if ( mParameter == mFromStr ) |
|
result = "From"; |
|
else if ( mParameter == mToStr ) |
|
result = "To"; |
|
else if ( mParameter == mCCStr ) |
|
result = "CC"; |
|
else if ( mParameter == mBCCStr ) |
|
result = "BCC"; |
|
|
|
result += '\t'; |
|
|
|
QMap<QString, KABC::Resource*>::const_iterator it = mResourceByName.constFind( mResourceName ); |
|
if ( it != mResourceByName.constEnd() ) |
|
result += it.value()->identifier(); |
|
else |
|
result += mStdResourceStr; |
|
|
|
result += '\t'; |
|
|
|
result += mCategory; |
|
|
|
return result; |
|
} |
|
|
|
void KMFilterActionAddToAddressBook::argsFromString( const QString &argsStr ) |
|
{ |
|
updateResourceMaps(); |
|
|
|
QStringList l = argsStr.split( '\t', QString::KeepEmptyParts ); |
|
mParameter = l[0]; |
|
|
|
if ( l.count() >= 2 ) { |
|
QMap<QString, KABC::Resource*>::iterator it = mResourceByID.find( l[1] ); |
|
if ( it != mResourceByID.end() ) |
|
mResourceName = it.value()->resourceName(); |
|
else |
|
mResourceName = mStdResourceStr; |
|
} else { |
|
mResourceName = mStdResourceStr; |
|
} |
|
|
|
if ( l.count() < 3 ) |
|
mCategory.clear(); |
|
else |
|
mCategory = l[2]; |
|
} |
|
|
|
//============================================================================= |
|
// |
|
// Filter Action Dictionary |
|
// |
|
//============================================================================= |
|
KMFilterActionDict::~KMFilterActionDict() |
|
{ |
|
qDeleteAll( mList ); |
|
} |
|
|
|
void KMFilterActionDict::init(void) |
|
{ |
|
insert( KMFilterActionMove::newAction ); |
|
insert( KMFilterActionCopy::newAction ); |
|
insert( KMFilterActionIdentity::newAction ); |
|
insert( KMFilterActionSetStatus::newAction ); |
|
insert( KMFilterActionAddTag::newAction ); |
|
insert( KMFilterActionFakeDisposition::newAction ); |
|
insert( KMFilterActionTransport::newAction ); |
|
insert( KMFilterActionReplyTo::newAction ); |
|
insert( KMFilterActionForward::newAction ); |
|
insert( KMFilterActionRedirect::newAction ); |
|
insert( KMFilterActionSendReceipt::newAction ); |
|
insert( KMFilterActionExec::newAction ); |
|
insert( KMFilterActionExtFilter::newAction ); |
|
insert( KMFilterActionRemoveHeader::newAction ); |
|
insert( KMFilterActionAddHeader::newAction ); |
|
insert( KMFilterActionRewriteHeader::newAction ); |
|
insert( KMFilterActionExecSound::newAction ); |
|
insert( KMFilterActionAddToAddressBook::newAction ); |
|
// Register custom filter actions below this line. |
|
} |
|
// The int in the QDict constructor (41) must be a prime |
|
// and should be greater than the double number of KMFilterAction types |
|
KMFilterActionDict::KMFilterActionDict() |
|
: QMultiHash<QString, KMFilterActionDesc*>() |
|
{ |
|
init(); |
|
} |
|
|
|
void KMFilterActionDict::insert( KMFilterActionNewFunc aNewFunc ) |
|
{ |
|
KMFilterAction *action = aNewFunc(); |
|
KMFilterActionDesc* desc = new KMFilterActionDesc; |
|
desc->name = action->name(); |
|
desc->label = action->label(); |
|
desc->create = aNewFunc; |
|
QMultiHash<QString, KMFilterActionDesc*>::insert( desc->name, desc ); |
|
QMultiHash<QString, KMFilterActionDesc*>::insert( desc->label, desc ); |
|
mList.append( desc ); |
|
delete action; |
|
} |
|
|
|
#include "kmfilteraction.moc"
|
|
|