File indexing completed on 2024-11-17 04:51:14

0001 /*
0002   SPDX-FileCopyrightText: 2015-2024 Laurent Montel <montel@kde.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "searchrulenumerical.h"
0008 
0009 #include "filter/filterlog.h"
0010 using MailCommon::FilterLog;
0011 
0012 #include <KMime/KMimeMessage>
0013 #include <QDateTime>
0014 
0015 #include <QRegularExpression>
0016 
0017 #include <algorithm>
0018 
0019 using namespace MailCommon;
0020 
0021 SearchRuleNumerical::SearchRuleNumerical(const QByteArray &field, Function func, const QString &contents)
0022     : SearchRule(field, func, contents)
0023 {
0024 }
0025 
0026 bool SearchRuleNumerical::isEmpty() const
0027 {
0028     bool ok = false;
0029     contents().toLongLong(&ok);
0030 
0031     return !ok;
0032 }
0033 
0034 bool SearchRuleNumerical::matches(const Akonadi::Item &item) const
0035 {
0036     if (!item.hasPayload<KMime::Message::Ptr>()) {
0037         return false;
0038     }
0039 
0040     const auto msg = item.payload<KMime::Message::Ptr>();
0041 
0042     QString msgContents;
0043     qint64 numericalMsgContents = 0;
0044     qint64 numericalValue = 0;
0045 
0046     if (qstricmp(field().constData(), "<size>") == 0) {
0047         numericalMsgContents = item.size();
0048         numericalValue = contents().toLongLong();
0049         msgContents.setNum(numericalMsgContents);
0050     } else if (qstricmp(field().constData(), "<age in days>") == 0) {
0051         QDateTime msgDateTime = msg->date()->dateTime();
0052         numericalMsgContents = msgDateTime.daysTo(QDateTime::currentDateTime());
0053         numericalValue = contents().toInt();
0054         msgContents.setNum(numericalMsgContents);
0055     } else {
0056         return false;
0057     }
0058     bool rc = matchesInternal(numericalValue, numericalMsgContents, msgContents);
0059     if (FilterLog::instance()->isLogging()) {
0060         QString msg = (rc ? QStringLiteral("<font color=#00FF00>1 = </font>") : QStringLiteral("<font color=#FF0000>0 = </font>"));
0061         msg += FilterLog::recode(asString());
0062         msg += QLatin1StringView(" ( <i>") + QString::number(numericalMsgContents) + QLatin1StringView("</i> )");
0063         FilterLog::instance()->add(msg, FilterLog::RuleResult);
0064     }
0065     return rc;
0066 }
0067 
0068 SearchRule::RequiredPart SearchRuleNumerical::requiredPart() const
0069 {
0070     return SearchRule::Envelope;
0071 }
0072 
0073 bool SearchRuleNumerical::matchesInternal(long numericalValue, long numericalMsgContents, const QString &msgContents) const
0074 {
0075     switch (function()) {
0076     case SearchRule::FuncEquals:
0077         return numericalValue == numericalMsgContents;
0078 
0079     case SearchRule::FuncNotEqual:
0080         return numericalValue != numericalMsgContents;
0081 
0082     case SearchRule::FuncContains:
0083         return msgContents.contains(contents(), Qt::CaseInsensitive);
0084 
0085     case SearchRule::FuncContainsNot:
0086         return !msgContents.contains(contents(), Qt::CaseInsensitive);
0087 
0088     case SearchRule::FuncRegExp:
0089         return msgContents.contains(QRegularExpression(contents(), QRegularExpression::CaseInsensitiveOption));
0090 
0091     case SearchRule::FuncNotRegExp:
0092         return !msgContents.contains(QRegularExpression(contents(), QRegularExpression::CaseInsensitiveOption));
0093 
0094     case FuncIsGreater:
0095         return numericalMsgContents > numericalValue;
0096 
0097     case FuncIsLessOrEqual:
0098         return numericalMsgContents <= numericalValue;
0099 
0100     case FuncIsLess:
0101         return numericalMsgContents < numericalValue;
0102 
0103     case FuncIsGreaterOrEqual:
0104         return numericalMsgContents >= numericalValue;
0105 
0106     case FuncIsInAddressbook: // since email-addresses are not numerical, I settle for false here
0107         return false;
0108 
0109     case FuncIsNotInAddressbook:
0110         return false;
0111 
0112     default:;
0113     }
0114 
0115     return false;
0116 }
0117 
0118 void SearchRuleNumerical::addQueryTerms(Akonadi::SearchTerm &groupTerm, bool &emptyIsNotAnError) const
0119 {
0120     using namespace Akonadi;
0121     emptyIsNotAnError = false;
0122     if (qstricmp(field().constData(), "<size>") == 0) {
0123         EmailSearchTerm term(EmailSearchTerm::ByteSize, contents().toInt(), akonadiComparator());
0124         term.setIsNegated(isNegated());
0125         groupTerm.addSubTerm(term);
0126     } else if (qstricmp(field().constData(), "<age in days>") == 0) {
0127         QDate date(QDate::currentDate());
0128         date = date.addDays(contents().toInt());
0129         EmailSearchTerm term(EmailSearchTerm::HeaderOnlyDate, date, akonadiComparator());
0130         term.setIsNegated(isNegated());
0131         groupTerm.addSubTerm(term);
0132     }
0133 }
0134 
0135 QString SearchRuleNumerical::informationAboutNotValidRules() const
0136 {
0137     return i18n("Content is not a number.");
0138 }