File indexing completed on 2025-01-05 04:49:33
0001 /* -*- mode: C++ -*- 0002 This file is part of KMail. 0003 SPDX-FileCopyrightText: 2003 Andreas Gungl <a.gungl@gmx.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-only 0006 */ 0007 0008 #pragma once 0009 0010 #include <KAssistantDialog> 0011 #include <KSharedConfig> 0012 0013 #include <Akonadi/Collection> 0014 #include <QList> 0015 0016 class QLabel; 0017 class QCheckBox; 0018 class QBoxLayout; 0019 class QListWidget; 0020 0021 namespace MailCommon 0022 { 0023 class FolderTreeWidget; 0024 class FolderRequester; 0025 } 0026 0027 namespace KMail 0028 { 0029 class ASWizInfoPage; 0030 class ASWizSpamRulesPage; 0031 class ASWizVirusRulesPage; 0032 class ASWizSummaryPage; 0033 0034 //--------------------------------------------------------------------------- 0035 /** 0036 @short KMail anti-spam wizard. 0037 @author Andreas Gungl <a.gungl@gmx.de> 0038 0039 The wizard helps to create filter rules to let KMail operate 0040 with external anti-spam tools. The wizard tries to detect the 0041 tools, but the user can override the preselections. 0042 Then the user can decide what functionality shall be supported 0043 by the created filter rules. 0044 The wizard will append the created filter rules after the 0045 last existing rule to keep possible conflicts with existing 0046 filter configurations minimal. 0047 0048 Anti-virus support was added by Fred Emmott <fred87@users.sf.net> 0049 0050 The configuration for the tools to get checked and set up 0051 is read from a config file. The structure of the file is as 0052 following: 0053 <pre> 0054 [General] 0055 tools=1 0056 0057 [Spamtool #1] 0058 Ident=spamassassin 0059 Version=0 0060 Priority=1 0061 VisibleName=&Spamassassin 0062 Executable=spamassassin -V 0063 URL=http://spamassassin.org 0064 PipeFilterName=SpamAssassin Check 0065 PipeCmdDetect=spamassassin -L 0066 ExecCmdSpam=sa-learn --spam --no-sync --single 0067 ExecCmdHam=sa-learn --ham --no-sync --single 0068 PipeCmdNoSpam=spamassassin -d 0069 DetectionHeader=X-Spam-Status 0070 DetectionPattern=yes 0071 DetectionPattern2= 0072 DetectionOnly=0 0073 UseRegExp=0 0074 SupportsBayes=1 0075 SupportsUnsure=0 0076 ServerSided=0 0077 type=spam 0078 </pre> 0079 The name of the config file is kmail.antispamrc 0080 and it's expected in the config dir of KDE. 0081 0082 */ 0083 class AntiSpamWizard : public KAssistantDialog 0084 { 0085 Q_OBJECT 0086 0087 public: 0088 /** The wizard can be used for setting up anti-spam tools and for 0089 setting up anti-virus tools. 0090 */ 0091 enum WizardMode { 0092 AntiSpam, 0093 AntiVirus, 0094 }; 0095 0096 /** Constructor that needs to initialize from the main folder tree 0097 of KMail. 0098 @param mode The mode the wizard should run in. 0099 @param parent The parent widget for the wizard. 0100 @param mainFolderTree The main folder tree from which the folders 0101 are copied to allow the selection of a spam folder in a tree 0102 within one of the wizard pages. 0103 */ 0104 AntiSpamWizard(WizardMode mode, QWidget *parent); 0105 0106 protected: 0107 /** 0108 Instances of this class store the settings for one tool as read from 0109 the config file. Visible name and What's this text cannot get 0110 translated! 0111 */ 0112 class SpamToolConfig 0113 { 0114 public: 0115 SpamToolConfig() = default; 0116 0117 SpamToolConfig(const QString &toolId, 0118 int configVersion, 0119 int prio, 0120 const QString &name, 0121 const QString &exec, 0122 const QString &url, 0123 const QString &filter, 0124 const QString &detection, 0125 const QString &spam, 0126 const QString &ham, 0127 const QString &noSpam, 0128 const QString &header, 0129 const QString &pattern, 0130 const QString &pattern2, 0131 const QString &serverPattern, 0132 bool detectionOnly, 0133 bool regExp, 0134 bool bayesFilter, 0135 bool tristateDetection, 0136 WizardMode type); 0137 0138 [[nodiscard]] int getVersion() const; 0139 [[nodiscard]] int getPrio() const; 0140 [[nodiscard]] QString getId() const; 0141 [[nodiscard]] QString getVisibleName() const; 0142 [[nodiscard]] QString getExecutable() const; 0143 [[nodiscard]] QString getWhatsThisText() const; 0144 [[nodiscard]] QString getFilterName() const; 0145 [[nodiscard]] QString getDetectCmd() const; 0146 [[nodiscard]] QString getSpamCmd() const; 0147 [[nodiscard]] QString getHamCmd() const; 0148 [[nodiscard]] QString getNoSpamCmd() const; 0149 [[nodiscard]] QString getDetectionHeader() const; 0150 [[nodiscard]] QString getDetectionPattern() const; 0151 [[nodiscard]] QString getDetectionPattern2() const; 0152 [[nodiscard]] QString getServerPattern() const; 0153 [[nodiscard]] bool isServerBased() const; 0154 [[nodiscard]] bool isDetectionOnly() const; 0155 [[nodiscard]] bool isUseRegExp() const; 0156 [[nodiscard]] bool useBayesFilter() const; 0157 [[nodiscard]] bool hasTristateDetection() const; 0158 [[nodiscard]] WizardMode getType() const; 0159 // convenience methods for types 0160 [[nodiscard]] bool isSpamTool() const; 0161 [[nodiscard]] bool isVirusTool() const; 0162 0163 private: 0164 // used to identify configs for the same tool 0165 QString mId; 0166 // The version of the config data, used for merging and 0167 // detecting newer configs 0168 int mVersion; 0169 // the priority of the tool in the list presented to the user 0170 int mPrio; 0171 // the name as shown by the checkbox in the dialog page 0172 QString mVisibleName; 0173 // the command to check the existence of the tool 0174 QString mExecutable; 0175 // the What's This help text (e.g. url for the tool) 0176 QString mWhatsThisText; 0177 // name for the created filter in the filter list 0178 QString mFilterName; 0179 // pipe through cmd used to detect spam messages 0180 QString mDetectCmd; 0181 // pipe through cmd to let the tool learn a spam message 0182 QString mSpamCmd; 0183 // pipe through cmd to let the tool learn a ham message 0184 QString mHamCmd; 0185 // pipe through cmd to let the tool delete the spam markup 0186 QString mNoSpamCmd; 0187 // by which header are messages marked as spam 0188 QString mDetectionHeader; 0189 // what header pattern is used to mark spam messages 0190 QString mDetectionPattern; 0191 // what header pattern is used to mark unsure messages 0192 QString mDetectionPattern2; 0193 // what header pattern is used in the account to check for a certain server 0194 QString mServerPattern; 0195 // filter cannot search actively but relies on pattern by regExp or contain rule 0196 bool mDetectionOnly; 0197 // filter searches for the pattern by regExp or contain rule 0198 bool mUseRegExp; 0199 // can the tool learn spam and ham, has it a bayesian algorithm 0200 bool mSupportsBayesFilter; 0201 // differentiate between ham, spam and a third "unsure" state 0202 bool mSupportsUnsure; 0203 // Is the tool AntiSpam or AntiVirus 0204 WizardMode mType; 0205 }; 0206 0207 /** 0208 Instances of this class control reading the configuration of the 0209 anti-spam tools from global and user config files as well as the 0210 merging of different config versions. 0211 */ 0212 class ConfigReader 0213 { 0214 public: 0215 ConfigReader(WizardMode mode, QList<SpamToolConfig> &configList); 0216 ~ConfigReader(); 0217 0218 QList<SpamToolConfig> &getToolList() 0219 { 0220 return mToolList; 0221 } 0222 0223 void readAndMergeConfig(); 0224 0225 private: 0226 QList<SpamToolConfig> &mToolList; 0227 KSharedConfig::Ptr mConfig; 0228 WizardMode mMode; 0229 0230 SpamToolConfig readToolConfig(KConfigGroup &configGroup); 0231 SpamToolConfig createDummyConfig(); 0232 0233 void mergeToolConfig(const SpamToolConfig &config); 0234 void sortToolList(); 0235 }; 0236 0237 /** Evaluate the settings made and create the appropriate filter rules. */ 0238 void accept() override; 0239 0240 protected Q_SLOTS: 0241 /** Modify the status of the wizard to reflect the selection of spam tools. */ 0242 void checkProgramsSelections(); 0243 /** Modify the status of the wizard to reflect the selected functionality. */ 0244 void checkVirusRulesSelections(); 0245 /** Check if the spam tools are available via the PATH */ 0246 void checkToolAvailability(); 0247 /** Show a help topic */ 0248 void slotHelpClicked(); 0249 /** Create the summary text based on the current settings */ 0250 void slotBuildSummary(); 0251 0252 private: 0253 /* Check for the availability of an executible along the PATH */ 0254 [[nodiscard]] int checkForProgram(const QString &executable) const; 0255 /* generic checks if any option in a page is checked */ 0256 [[nodiscard]] bool anyVirusOptionChecked() const; 0257 /* convenience method calling the appropriate filter manager method */ 0258 const QString uniqueNameFor(const QString &name); 0259 /* convenience method to sort out new and existing filters */ 0260 void sortFilterOnExistance(const QString &intendedFilterName, QString &newFilters, QString &replaceFilters); 0261 0262 /* The pages in the wizard */ 0263 ASWizInfoPage *mInfoPage = nullptr; 0264 ASWizSpamRulesPage *mSpamRulesPage = nullptr; 0265 ASWizVirusRulesPage *mVirusRulesPage = nullptr; 0266 ASWizSummaryPage *mSummaryPage = nullptr; 0267 0268 KPageWidgetItem *mInfoPageItem = nullptr; 0269 KPageWidgetItem *mSpamRulesPageItem = nullptr; 0270 KPageWidgetItem *mVirusRulesPageItem = nullptr; 0271 KPageWidgetItem *mSummaryPageItem = nullptr; 0272 0273 /* The configured tools and it's settings to be used in the wizard. */ 0274 QList<SpamToolConfig> mToolList; 0275 0276 /* Are any spam tools selected? */ 0277 bool mSpamToolsUsed; 0278 /* Are any virus tools selected? */ 0279 bool mVirusToolsUsed; 0280 0281 WizardMode mMode; 0282 }; 0283 0284 //--------------------------------------------------------------------------- 0285 class ASWizPage : public QWidget 0286 { 0287 Q_OBJECT 0288 public: 0289 ASWizPage(QWidget *parent, const QString &name); 0290 0291 protected: 0292 QBoxLayout *mLayout = nullptr; 0293 }; 0294 0295 //--------------------------------------------------------------------------- 0296 class ASWizInfoPage : public ASWizPage 0297 { 0298 Q_OBJECT 0299 0300 public: 0301 ASWizInfoPage(AntiSpamWizard::WizardMode mode, QWidget *parent, const QString &name); 0302 0303 void setScanProgressText(const QString &toolName); 0304 void addAvailableTool(const QString &visibleName); 0305 [[nodiscard]] bool isProgramSelected(const QString &visibleName) const; 0306 0307 Q_SIGNALS: 0308 void selectionChanged(); 0309 0310 private: 0311 void processSelectionChange(); 0312 QLabel *mScanProgressText = nullptr; 0313 QLabel *mSelectionHint = nullptr; 0314 QListWidget *mToolsList = nullptr; 0315 }; 0316 0317 //--------------------------------------------------------------------------- 0318 class ASWizSpamRulesPage : public ASWizPage 0319 { 0320 Q_OBJECT 0321 0322 public: 0323 ASWizSpamRulesPage(QWidget *parent, const QString &name); 0324 0325 [[nodiscard]] bool markAsReadSelected() const; 0326 [[nodiscard]] bool moveSpamSelected() const; 0327 [[nodiscard]] bool moveUnsureSelected() const; 0328 0329 [[nodiscard]] QString selectedUnsureCollectionName() const; 0330 [[nodiscard]] QString selectedUnsureCollectionId() const; 0331 0332 void allowUnsureFolderSelection(bool enabled); 0333 void allowMoveSpam(bool enabled); 0334 0335 [[nodiscard]] QString selectedSpamCollectionId() const; 0336 [[nodiscard]] QString selectedSpamCollectionName() const; 0337 0338 protected: 0339 Akonadi::Collection selectedSpamCollection() const; 0340 Akonadi::Collection selectedUnsureCollection() const; 0341 0342 Q_SIGNALS: 0343 void selectionChanged(); 0344 0345 private: 0346 void processSelectionChange(); 0347 QCheckBox *mMarkRules = nullptr; 0348 QCheckBox *mMoveSpamRules = nullptr; 0349 QCheckBox *mMoveUnsureRules = nullptr; 0350 MailCommon::FolderRequester *mFolderReqForSpamFolder = nullptr; 0351 MailCommon::FolderRequester *mFolderReqForUnsureFolder = nullptr; 0352 }; 0353 0354 //------------------------------------------------------------------------- 0355 class ASWizVirusRulesPage : public ASWizPage 0356 { 0357 Q_OBJECT 0358 0359 public: 0360 ASWizVirusRulesPage(QWidget *parent, const QString &name); 0361 0362 [[nodiscard]] bool pipeRulesSelected() const; 0363 [[nodiscard]] bool moveRulesSelected() const; 0364 [[nodiscard]] bool markReadRulesSelected() const; 0365 0366 [[nodiscard]] QString selectedFolderName() const; 0367 0368 Q_SIGNALS: 0369 void selectionChanged(); 0370 0371 private: 0372 void processSelectionChange(); 0373 QCheckBox *mPipeRules = nullptr; 0374 QCheckBox *mMoveRules = nullptr; 0375 MailCommon::FolderTreeWidget *mFolderTree = nullptr; 0376 QCheckBox *mMarkRules = nullptr; 0377 }; 0378 0379 //--------------------------------------------------------------------------- 0380 class ASWizSummaryPage : public ASWizPage 0381 { 0382 Q_OBJECT 0383 0384 public: 0385 ASWizSummaryPage(QWidget *parent, const QString &name); 0386 0387 void setSummaryText(const QString &text); 0388 0389 private: 0390 QLabel *const mSummaryText; 0391 }; 0392 } // namespace KMail