File indexing completed on 2024-11-10 04:50:07
0001 /* 0002 SPDX-FileCopyrightText: 2003 Andreas Gungl <a.gungl@gmx.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-only 0005 */ 0006 0007 #include "filterlog.h" 0008 0009 #include "mailcommon_debug.h" 0010 0011 #include <QFile> 0012 #include <QTime> 0013 0014 #include <sys/stat.h> 0015 0016 using namespace MailCommon; 0017 0018 class Q_DECL_HIDDEN FilterLog::FilterLogPrivate 0019 { 0020 public: 0021 FilterLogPrivate(FilterLog *qq) 0022 : q(qq) 0023 , mMaxLogSize(512 * 1024) 0024 , mAllowedTypes(FilterLog::Meta | FilterLog::PatternDescription | FilterLog::RuleResult | FilterLog::PatternResult | FilterLog::AppliedAction) 0025 { 0026 } 0027 0028 static FilterLog *mSelf; 0029 0030 FilterLog *const q; 0031 QStringList mLogEntries; 0032 long mMaxLogSize; 0033 long mCurrentLogSize = 0; 0034 int mAllowedTypes; 0035 bool mLogging = false; 0036 0037 void checkLogSize(); 0038 }; 0039 0040 void FilterLog::FilterLogPrivate::checkLogSize() 0041 { 0042 if (mCurrentLogSize > mMaxLogSize && mMaxLogSize > -1) { 0043 qCDebug(MAILCOMMON_LOG) << "Filter log: memory limit reached, starting to discard old items, size =" << QString::number(mCurrentLogSize); 0044 0045 // avoid some kind of hysteresis, shrink the log to 90% of its maximum 0046 while (mCurrentLogSize > (mMaxLogSize * 0.9)) { 0047 QStringList::Iterator it = mLogEntries.begin(); 0048 if (it != mLogEntries.end()) { 0049 mCurrentLogSize -= (*it).length(); 0050 mLogEntries.erase(it); 0051 qCDebug(MAILCOMMON_LOG) << "Filter log: new size =" << QString::number(mCurrentLogSize); 0052 } else { 0053 qCDebug(MAILCOMMON_LOG) << "Filter log: size reduction disaster!"; 0054 q->clear(); 0055 } 0056 } 0057 0058 Q_EMIT q->logShrinked(); 0059 } 0060 } 0061 0062 FilterLog *FilterLog::FilterLogPrivate::mSelf = nullptr; 0063 0064 FilterLog::FilterLog() 0065 : d(new FilterLogPrivate(this)) 0066 { 0067 } 0068 0069 FilterLog::~FilterLog() = default; 0070 0071 FilterLog *FilterLog::instance() 0072 { 0073 if (!FilterLog::FilterLogPrivate::mSelf) { 0074 FilterLog::FilterLogPrivate::mSelf = new FilterLog(); 0075 } 0076 0077 return FilterLog::FilterLogPrivate::mSelf; 0078 } 0079 0080 bool FilterLog::isLogging() const 0081 { 0082 return d->mLogging; 0083 } 0084 0085 void FilterLog::setLogging(bool active) 0086 { 0087 d->mLogging = active; 0088 Q_EMIT logStateChanged(); 0089 } 0090 0091 void FilterLog::setMaxLogSize(long size) 0092 { 0093 if (size < -1) { 0094 size = -1; 0095 } 0096 0097 // do not allow less than 1 KByte except unlimited (-1) 0098 if (size >= 0 && size < 1024) { 0099 size = 1024; 0100 } 0101 0102 d->mMaxLogSize = size; 0103 Q_EMIT logStateChanged(); 0104 d->checkLogSize(); 0105 } 0106 0107 long FilterLog::maxLogSize() const 0108 { 0109 return d->mMaxLogSize; 0110 } 0111 0112 void FilterLog::setContentTypeEnabled(ContentType contentType, bool enable) 0113 { 0114 if (enable) { 0115 d->mAllowedTypes |= contentType; 0116 } else { 0117 d->mAllowedTypes &= ~contentType; 0118 } 0119 0120 Q_EMIT logStateChanged(); 0121 } 0122 0123 bool FilterLog::isContentTypeEnabled(ContentType contentType) const 0124 { 0125 return d->mAllowedTypes & contentType; 0126 } 0127 0128 void FilterLog::add(const QString &logEntry, ContentType contentType) 0129 { 0130 if (isLogging() && (d->mAllowedTypes & contentType)) { 0131 QString timedLog; 0132 if (contentType & ~Meta) { 0133 timedLog = QLatin1Char('[') + QTime::currentTime().toString() + QLatin1StringView("] ") + logEntry; 0134 } else { 0135 timedLog = logEntry; 0136 } 0137 0138 d->mLogEntries.append(timedLog); 0139 Q_EMIT logEntryAdded(timedLog); 0140 d->mCurrentLogSize += timedLog.length(); 0141 d->checkLogSize(); 0142 } 0143 } 0144 0145 void FilterLog::addSeparator() 0146 { 0147 add(QStringLiteral("------------------------------"), Meta); 0148 } 0149 0150 void FilterLog::clear() 0151 { 0152 d->mLogEntries.clear(); 0153 d->mCurrentLogSize = 0; 0154 } 0155 0156 QStringList FilterLog::logEntries() const 0157 { 0158 return d->mLogEntries; 0159 } 0160 0161 void FilterLog::dump() 0162 { 0163 qCDebug(MAILCOMMON_LOG) << "----- starting filter log -----"; 0164 for (const QString &entry : std::as_const(d->mLogEntries)) { 0165 qCDebug(MAILCOMMON_LOG) << entry; 0166 } 0167 qCDebug(MAILCOMMON_LOG) << "------ end of filter log ------"; 0168 } 0169 0170 bool FilterLog::saveToFile(const QString &fileName) const 0171 { 0172 QFile file(fileName); 0173 if (!file.open(QIODevice::WriteOnly)) { 0174 return false; 0175 } 0176 0177 file.write("<html>\n<body>\n"); 0178 file.write("<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n"); 0179 for (const QString &entry : std::as_const(d->mLogEntries)) { 0180 const QString line = QLatin1StringView("<p>") + entry + QLatin1StringView("</p>") + QLatin1Char('\n'); 0181 file.write(line.toLocal8Bit()); 0182 } 0183 file.write("</body>\n</html>\n"); 0184 file.close(); 0185 return true; 0186 } 0187 0188 QString FilterLog::recode(const QString &plain) 0189 { 0190 return plain.toHtmlEscaped(); 0191 } 0192 0193 #include "moc_filterlog.cpp"