// kmfilteraction.cpp // The process methods really should use an enum instead of an int // -1 -> status unchanged, 0 -> success, 1 -> failure, 2-> critical failure #include "kmmessage.h" #include "kmmsgpart.h" #include "kmfilteraction.h" #include "kmfiltermgr.h" #include "kmfoldermgr.h" #include "kmfolder.h" #include "kmglobal.h" #include "kmsender.h" #include "kmidentity.h" #include "kfileio.h" #include #include #include #include #include #include #include #include #include #include #include //for alarm (sven) #include #include #include static QString resultStr; //----------------------------------------------------------------------------- KMFilterAction::KMFilterAction(const char* name): KMFilterActionInherited(NULL, name) { } KMFilterAction::~KMFilterAction() { } KMFilterAction* KMFilterAction::newAction(void) { return NULL; } QWidget* KMFilterAction::createParamWidget(KMGFilterDlg*) { return NULL; } void KMFilterAction::applyParamWidgetValue(QWidget*) { } bool KMFilterAction::folderRemoved(KMFolder*, KMFolder*) { return FALSE; } int KMFilterAction::tempOpenFolder(KMFolder* aFolder) { return kernel->filterMgr()->tempOpenFolder(aFolder); } //============================================================================= // // Specific Filter Actions // //============================================================================= //============================================================================= // Move message to another mail folder //============================================================================= class KMFilterActionMove: public KMFilterAction { public: KMFilterActionMove(); virtual QString label(void) const; virtual int process(KMMessage* msg, bool& stopIt); virtual QWidget* createParamWidget(KMGFilterDlg* parent); virtual void applyParamWidgetValue(QWidget* paramWidget); virtual void argsFromString(const QString &argsStr); virtual QString argsAsString(void) const; virtual bool folderRemoved(KMFolder* aFolder, KMFolder* aNewFolder); static KMFilterAction* newAction(void); protected: QGuardedPtr mDest; QValueList > gfolders; }; bool KMFilterActionMove::folderRemoved(KMFolder* aFolder, KMFolder* aNewFolder) { if (aFolder==mDest) { mDest = aNewFolder; } return TRUE; } KMFilterAction* KMFilterActionMove::newAction(void) { return (new KMFilterActionMove); } QString KMFilterActionMove::label(void) const { return i18n("transfer"); } KMFilterActionMove::KMFilterActionMove(): KMFilterAction("transfer") { mDest = NULL; } int KMFilterActionMove::process(KMMessage* msg, bool&stopIt) { if (!mDest) return 1; KMFilterAction::tempOpenFolder(mDest); if (msg->parent()) return 0; if (mDest->moveMsg(msg) == 0) return 0; // ok, added else { kdDebug() << "KMfilteraction - couldn't move msg" << endl; stopIt = TRUE; return 2; // critical error: couldn't add } } QWidget* KMFilterActionMove::createParamWidget(KMGFilterDlg* aParent) { QString name; QComboBox* cbx; QStringList str; gfolders.clear(); kernel->folderMgr()->createI18nFolderList( &str, &gfolders ); cbx = aParent->createFolderCombo( &str, &gfolders, mDest ); return cbx; } void KMFilterActionMove::applyParamWidgetValue(QWidget* aParamWidget) { QComboBox* cbx = (QComboBox*)aParamWidget; if ((cbx->currentItem() >= 0) && (cbx->currentItem() < (int)gfolders.count())) mDest = (*gfolders.at(cbx->currentItem())); else mDest = 0; } void KMFilterActionMove::argsFromString(const QString &argsStr) { mDest = (KMFolder*)kernel->folderMgr()->findIdString(argsStr); } QString KMFilterActionMove::argsAsString(void) const { if (mDest) resultStr = mDest->idString(); else resultStr = ""; return resultStr; } //============================================================================= // Forward message to another user //============================================================================= class KMFilterActionForward: public KMFilterAction { public: KMFilterActionForward(); virtual QString label(void) const; virtual int process(KMMessage* msg, bool& stopIt); virtual QWidget* createParamWidget(KMGFilterDlg* parent); virtual void applyParamWidgetValue(QWidget* paramWidget); virtual void argsFromString(const QString& argsStr); virtual QString argsAsString(void) const; static KMFilterAction* newAction(void); protected: QString mTo; }; KMFilterAction* KMFilterActionForward::newAction(void) { return (new KMFilterActionForward); } QString KMFilterActionForward::label(void) const { return i18n("forward to"); } KMFilterActionForward::KMFilterActionForward(): KMFilterAction("forward") { } int KMFilterActionForward::process(KMMessage* aMsg, bool& /*stop*/) { KMMessage* msg; if (mTo.isEmpty()) return 1; msg = aMsg->createForward(); msg->setTo(mTo); if (!kernel->msgSender()->send(msg)) { kdDebug() << "KMFilterActionForward: could not forward message (sending failed)" << endl; return 1; // error: couldn't send } return -1; } QWidget* KMFilterActionForward::createParamWidget(KMGFilterDlg* aParent) { QLineEdit* edt; edt = aParent->createEdit(mTo); return edt; } void KMFilterActionForward::applyParamWidgetValue(QWidget* aParamWidget) { QLineEdit* w = (QLineEdit*)aParamWidget; mTo = w->text(); } void KMFilterActionForward::argsFromString(const QString &argsStr) { mTo = argsStr; } QString KMFilterActionForward::argsAsString(void) const { return mTo; } //============================================================================= // Execute a shell command //============================================================================= class KMFilterActionExec:public KMFilterAction { public: KMFilterActionExec(const char* name = "execute"); virtual QString label(void) const; virtual int process(KMMessage* msg, bool& stopIt); virtual QWidget* createParamWidget(KMGFilterDlg* parent); virtual void applyParamWidgetValue(QWidget* paramWidget); virtual void argsFromString(const QString &argsStr); virtual QString argsAsString(void) const; static KMFilterAction* newAction(void); static void dummySigHandler(int); protected: QString mCmd; }; KMFilterAction* KMFilterActionExec::newAction(void) { return (new KMFilterActionExec); } QString KMFilterActionExec::label(void) const { return i18n("execute"); } KMFilterActionExec::KMFilterActionExec(const char* aName) : KMFilterAction(aName) { } void KMFilterActionExec::dummySigHandler(int) { } int KMFilterActionExec::process(KMMessage *aMsg, bool& /*stop*/) { void (*oldSigHandler)(int); int rc; if (mCmd.isEmpty()) return 1; QString fullCmd = mCmd + " "; QList atmList; KMMessagePart msgPart; int i, nr; while (fullCmd.contains("%")) { i = fullCmd.find("%") + 1; nr = fullCmd.mid(i, fullCmd.find(" ", i) - i).toInt(); aMsg->bodyPart(nr, &msgPart); KTempFile *atmTempFile = new KTempFile(); atmList.append( atmTempFile ); atmTempFile->setAutoDelete( true ); kByteArrayToFile(msgPart.bodyDecodedBinary(), atmTempFile->name(), false, false, false); fullCmd = fullCmd.arg( atmTempFile->name() ); } oldSigHandler = signal(SIGALRM, &KMFilterActionExec::dummySigHandler); alarm(30); rc = system(fullCmd.left(fullCmd.length() - 1 )); alarm(0); signal(SIGALRM, oldSigHandler); if (rc & 255) return 1; else return -1; } QWidget* KMFilterActionExec::createParamWidget(KMGFilterDlg* aParent) { QLineEdit* edt; edt = aParent->createEdit(mCmd); return edt; } void KMFilterActionExec::applyParamWidgetValue(QWidget* aParamWidget) { QLineEdit* w = (QLineEdit*)aParamWidget; mCmd = w->text(); } void KMFilterActionExec::argsFromString(const QString &argsStr) { mCmd = argsStr; } QString KMFilterActionExec::argsAsString(void) const { return mCmd; } //============================================================================= // External message filter: executes a shell command with message // on stdin; altered message is expected on stdout. //============================================================================= class KMFilterActionExtFilter: public KMFilterActionExec { public: KMFilterActionExtFilter(const char* name = "filter app"); virtual QString label(void) const; static KMFilterAction* newAction(void); virtual int process(KMMessage* msg, bool& stopIt); }; KMFilterAction* KMFilterActionExtFilter::newAction(void) { return (new KMFilterActionExtFilter); } QString KMFilterActionExtFilter::label(void) const { return i18n("filter app"); } KMFilterActionExtFilter::KMFilterActionExtFilter(const char* aName) : KMFilterActionExec(aName) { } int KMFilterActionExtFilter::process(KMMessage* aMsg, bool& stop) { int rc=0, len; QString msgText, origCmd; char buf[8192]; FILE *fh; bool ok = TRUE; KTempFile inFile(locateLocal("tmp", "kmail-filter"), "in"); KTempFile outFile(locateLocal("tmp", "kmail-filter"), "out"); if (mCmd.isEmpty()) return 1; // write message to file fh = inFile.fstream(); if (fh) { msgText = aMsg->asString(); if (!fwrite(msgText, msgText.length(), 1, fh)) ok = FALSE; inFile.close(); } else ok = FALSE; outFile.close(); if (ok) { // execute filter origCmd = mCmd; mCmd = mCmd + " <" + inFile.name() + " >" + outFile.name(); rc = KMFilterActionExec::process(aMsg, stop); mCmd = origCmd; // read altered message fh = fopen(outFile.name(), "r"); if (fh) { msgText = ""; while (1) { len = fread(buf, 1, 1023, fh); if (len <= 0) break; buf[len] = 0; msgText += buf; } outFile.close(); if (!msgText.isEmpty()) aMsg->fromString(msgText); } else ok = FALSE; } inFile.unlink(); outFile.unlink(); return rc; } //============================================================================= // Specify Identity to be used when replying to a message //============================================================================= class KMFilterActionIdentity: public KMFilterAction { public: KMFilterActionIdentity(); virtual QString label(void) const; virtual int process(KMMessage* msg, bool& stopIt); virtual QWidget* createParamWidget(KMGFilterDlg* parent); virtual void applyParamWidgetValue(QWidget* paramWidget); virtual void argsFromString(const QString &argsStr); virtual QString argsAsString(void) const; static KMFilterAction* newAction(void); protected: QStringList ids; QString id; }; KMFilterAction* KMFilterActionIdentity::newAction(void) { return (new KMFilterActionIdentity); } QString KMFilterActionIdentity::label(void) const { return i18n("set identity"); } KMFilterActionIdentity::KMFilterActionIdentity(): KMFilterAction("set identity") { id = i18n( "Default" ); } int KMFilterActionIdentity::process(KMMessage* msg, bool& ) { msg->setHeaderField( "X-KMail-Identity", id ); return -1; } QWidget* KMFilterActionIdentity::createParamWidget(KMGFilterDlg* aParent) { QStringList ids = KMIdentity::identities(); QComboBox *cbx = aParent->createCombo( &ids, id ); return cbx; } void KMFilterActionIdentity::applyParamWidgetValue(QWidget* aParamWidget) { QComboBox* cbx = (QComboBox*)aParamWidget; id = cbx->currentText(); } void KMFilterActionIdentity::argsFromString(const QString &argsStr) { if (argsStr.isEmpty()) id = i18n( "Default" ); else id = argsStr; } QString KMFilterActionIdentity::argsAsString(void) const { if (id == i18n( "Default" )) return ""; else return id; } //============================================================================= // Specify mail transport (smtp server) to be used when replying to a message //============================================================================= class KMFilterActionTransport: public KMFilterAction { public: KMFilterActionTransport(); virtual QString label(void) const; virtual int process(KMMessage* msg, bool& stopIt); virtual QWidget* createParamWidget(KMGFilterDlg* parent); virtual void applyParamWidgetValue(QWidget* paramWidget); virtual void argsFromString(const QString& argsStr); virtual QString argsAsString(void) const; static KMFilterAction* newAction(void); protected: QString mTransport; }; KMFilterAction* KMFilterActionTransport::newAction(void) { return (new KMFilterActionTransport); } QString KMFilterActionTransport::label(void) const { return i18n("set transport"); } KMFilterActionTransport::KMFilterActionTransport(): KMFilterAction("set transport") { mTransport = kernel->msgSender()->transportString(); } int KMFilterActionTransport::process(KMMessage* msg, bool& ) { msg->setHeaderField( "X-KMail-Transport", mTransport ); return -1; } QWidget* KMFilterActionTransport::createParamWidget(KMGFilterDlg* aParent) { QLineEdit* edt; edt = aParent->createEdit(mTransport); return edt; } void KMFilterActionTransport::applyParamWidgetValue(QWidget* aParamWidget) { QLineEdit* w = (QLineEdit*)aParamWidget; mTransport = w->text(); } void KMFilterActionTransport::argsFromString(const QString &argsStr) { mTransport = argsStr; } QString KMFilterActionTransport::argsAsString(void) const { return mTransport; } //============================================================================= // Set the Reply-to header in a message //============================================================================= class KMFilterActionReplyTo: public KMFilterAction { public: KMFilterActionReplyTo(); virtual QString label(void) const; virtual int process(KMMessage* msg, bool& stopIt); virtual QWidget* createParamWidget(KMGFilterDlg* parent); virtual void applyParamWidgetValue(QWidget* paramWidget); virtual void argsFromString(const QString &argsStr); virtual QString argsAsString(void) const; static KMFilterAction* newAction(void); protected: QString mReplyTo; }; KMFilterAction* KMFilterActionReplyTo::newAction(void) { return (new KMFilterActionReplyTo); } QString KMFilterActionReplyTo::label(void) const { return i18n("set Reply-To"); } KMFilterActionReplyTo::KMFilterActionReplyTo(): KMFilterAction("set Reply-To") { mReplyTo = ""; } int KMFilterActionReplyTo::process(KMMessage* msg, bool& ) { msg->setHeaderField( "Reply-To", mReplyTo ); return -1; } QWidget* KMFilterActionReplyTo::createParamWidget(KMGFilterDlg* aParent) { QLineEdit* edt; edt = aParent->createEdit(mReplyTo); return edt; } void KMFilterActionReplyTo::applyParamWidgetValue(QWidget* aParamWidget) { QLineEdit* w = (QLineEdit*)aParamWidget; mReplyTo = w->text(); } void KMFilterActionReplyTo::argsFromString(const QString &argsStr) { mReplyTo = argsStr; } QString KMFilterActionReplyTo::argsAsString(void) const { return mReplyTo; } //============================================================================= // // Filter Action Dictionary // //============================================================================= void KMFilterActionDict::init(void) { mList.setAutoDelete(true); insert("transfer", i18n("transfer"), KMFilterActionMove::newAction); insert("set identity", i18n("set identity"), KMFilterActionIdentity::newAction); insert("set transport", i18n("set transport"), KMFilterActionTransport::newAction); insert("set Reply-To", i18n("set Reply-To"), KMFilterActionReplyTo::newAction); insert("forward", i18n("forward to"), KMFilterActionForward::newAction); insert("execute", i18n("execute"), KMFilterActionExec::newAction); insert("filter app", i18n("filter app"), KMFilterActionExtFilter::newAction); // Register custom filter actions below this line. } KMFilterActionDict::KMFilterActionDict(): mList() { init(); } KMFilterActionDict::~KMFilterActionDict() { } void KMFilterActionDict::insert(const QString &aName, const QString &aLabel, KMFilterActionNewFunc aFunc) { KMFilterActionDesc* desc = new KMFilterActionDesc; desc->name = aName; desc->label = aLabel; desc->func = aFunc; mList.append(desc); } KMFilterAction* KMFilterActionDict::create(const QString &name) { KMFilterActionDesc* desc = find(name); if (desc) return desc->func(); return NULL; } int KMFilterActionDict::indexOf(const QString &aName) { KMFilterActionDesc* desc; int i; for (i=0,desc=mList.first(); desc; i++,desc=mList.next()) if (desc->name==aName) return i; return -1; } QString KMFilterActionDict::labelOf(const QString &aName) { KMFilterActionDesc* desc = find(aName); if (desc) return desc->label; return ""; } QString KMFilterActionDict::nameOf(const QString &aLabel) { KMFilterActionDesc* desc; for (desc=mList.first(); desc; desc=mList.next()) if (desc->label==aLabel) return desc->name; return ""; } KMFilterActionDesc* KMFilterActionDict::find(const QString &aName) { KMFilterActionDesc* desc; for (desc=mList.first(); desc; desc=mList.next()) if (desc->name==aName) return desc; return NULL; } QString KMFilterActionDict::first(void) { KMFilterActionDesc* desc = mList.first(); if (!desc) return ""; return desc->name; } QString KMFilterActionDict::next(void) { KMFilterActionDesc* desc = mList.next(); if (!desc) return ""; return desc->name; } QString KMFilterActionDict::currentName(void) { return mList.current()->name; } QString KMFilterActionDict::currentLabel(void) { return mList.current()->label; } KMFilterAction* KMFilterActionDict::currentCreate(void) { return mList.current()->func(); } //============================================================================= // // Generic Filter Action Dialog // //============================================================================= KMGFilterDlg::KMGFilterDlg(QWidget* parent, const char* name, bool modal, WFlags f): KMGFilterDlgInherited(parent, name, modal, f) { initMetaObject(); } //----------------------------------------------------------------------------- KMGFilterDlg::~KMGFilterDlg() { } //----------------------------------------------------------------------------- #include "kmfilteraction.moc"