1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 by the Quassel Project * |
3 | * devel@quassel-irc.org * |
4 | * * |
5 | * This program is free software; you can redistribute it and/or modify * |
6 | * it under the terms of the GNU General Public License as published by * |
7 | * the Free Software Foundation; either version 2 of the License, or * |
8 | * (at your option) version 3. * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the * |
17 | * Free Software Foundation, Inc., * |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
19 | ***************************************************************************/ |
20 | |
21 | #include "ignorelistmanager.h" |
22 | |
23 | #include <QtCore> |
24 | #include <QDebug> |
25 | #include <QStringList> |
26 | |
27 | INIT_SYNCABLE_OBJECT(IgnoreListManager) |
28 | IgnoreListManager &IgnoreListManager::operator=(const IgnoreListManager &other) |
29 | { |
30 | if (this == &other) |
31 | return *this; |
32 | |
33 | SyncableObject::operator=(other); |
34 | _ignoreList = other._ignoreList; |
35 | return *this; |
36 | } |
37 | |
38 | |
39 | int IgnoreListManager::indexOf(const QString &ignore) const |
40 | { |
41 | for (int i = 0; i < _ignoreList.count(); i++) { |
42 | if (_ignoreList[i].ignoreRule == ignore) |
43 | return i; |
44 | } |
45 | return -1; |
46 | } |
47 | |
48 | |
49 | QVariantMap IgnoreListManager::initIgnoreList() const |
50 | { |
51 | QVariantMap ignoreListMap; |
52 | QVariantList ignoreTypeList; |
53 | QStringList ignoreRuleList; |
54 | QStringList scopeRuleList; |
55 | QVariantList isRegExList; |
56 | QVariantList scopeList; |
57 | QVariantList strictnessList; |
58 | QVariantList isActiveList; |
59 | |
60 | for (int i = 0; i < _ignoreList.count(); i++) { |
61 | ignoreTypeList << _ignoreList[i].type; |
62 | ignoreRuleList << _ignoreList[i].ignoreRule; |
63 | scopeRuleList << _ignoreList[i].scopeRule; |
64 | isRegExList << _ignoreList[i].isRegEx; |
65 | scopeList << _ignoreList[i].scope; |
66 | strictnessList << _ignoreList[i].strictness; |
67 | isActiveList << _ignoreList[i].isActive; |
68 | } |
69 | |
70 | ignoreListMap["ignoreType" ] = ignoreTypeList; |
71 | ignoreListMap["ignoreRule" ] = ignoreRuleList; |
72 | ignoreListMap["scopeRule" ] = scopeRuleList; |
73 | ignoreListMap["isRegEx" ] = isRegExList; |
74 | ignoreListMap["scope" ] = scopeList; |
75 | ignoreListMap["strictness" ] = strictnessList; |
76 | ignoreListMap["isActive" ] = isActiveList; |
77 | return ignoreListMap; |
78 | } |
79 | |
80 | |
81 | void IgnoreListManager::initSetIgnoreList(const QVariantMap &ignoreList) |
82 | { |
83 | QVariantList ignoreType = ignoreList["ignoreType" ].toList(); |
84 | QStringList ignoreRule = ignoreList["ignoreRule" ].toStringList(); |
85 | QStringList scopeRule = ignoreList["scopeRule" ].toStringList(); |
86 | QVariantList isRegEx = ignoreList["isRegEx" ].toList(); |
87 | QVariantList scope = ignoreList["scope" ].toList(); |
88 | QVariantList strictness = ignoreList["strictness" ].toList(); |
89 | QVariantList isActive = ignoreList["isActive" ].toList(); |
90 | |
91 | int count = ignoreRule.count(); |
92 | if (count != scopeRule.count() || count != isRegEx.count() || |
93 | count != scope.count() || count != strictness.count() || count != ignoreType.count() || count != isActive.count()) { |
94 | qWarning() << "Corrupted IgnoreList settings! (Count missmatch)" ; |
95 | return; |
96 | } |
97 | |
98 | _ignoreList.clear(); |
99 | for (int i = 0; i < ignoreRule.count(); i++) { |
100 | _ignoreList << IgnoreListItem(static_cast<IgnoreType>(ignoreType[i].toInt()), ignoreRule[i], isRegEx[i].toBool(), |
101 | static_cast<StrictnessType>(strictness[i].toInt()), static_cast<ScopeType>(scope[i].toInt()), |
102 | scopeRule[i], isActive[i].toBool()); |
103 | } |
104 | } |
105 | |
106 | |
107 | /* since overloaded methods aren't syncable (yet?) we can't use that anymore |
108 | void IgnoreListManager::addIgnoreListItem(const IgnoreListItem &item) { |
109 | addIgnoreListItem(item.type, item.ignoreRule, item.isRegEx, item.strictness, item.scope, item.scopeRule, item.isActive); |
110 | } |
111 | */ |
112 | void IgnoreListManager::addIgnoreListItem(int type, const QString &ignoreRule, bool isRegEx, int strictness, |
113 | int scope, const QString &scopeRule, bool isActive) |
114 | { |
115 | if (contains(ignoreRule)) { |
116 | return; |
117 | } |
118 | |
119 | IgnoreListItem newItem = IgnoreListItem(static_cast<IgnoreType>(type), ignoreRule, isRegEx, static_cast<StrictnessType>(strictness), |
120 | static_cast<ScopeType>(scope), scopeRule, isActive); |
121 | _ignoreList << newItem; |
122 | |
123 | SYNC(ARG(type), ARG(ignoreRule), ARG(isRegEx), ARG(strictness), ARG(scope), ARG(scopeRule), ARG(isActive)) |
124 | } |
125 | |
126 | |
127 | IgnoreListManager::StrictnessType IgnoreListManager::_match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName) |
128 | { |
129 | // We method don't rely on a proper Message object to make this method more versatile. |
130 | // This allows us to use it in the core with unprocessed Messages or in the Client |
131 | // with properly preprocessed Messages. |
132 | if (!(msgType & (Message::Plain | Message::Notice | Message::Action))) |
133 | return UnmatchedStrictness; |
134 | |
135 | foreach(IgnoreListItem item, _ignoreList) { |
136 | if (!item.isActive || item.type == CtcpIgnore) |
137 | continue; |
138 | if (item.scope == GlobalScope |
139 | || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network)) |
140 | || (item.scope == ChannelScope && scopeMatch(item.scopeRule, bufferName))) { |
141 | QString str; |
142 | if (item.type == MessageIgnore) |
143 | str = msgContents; |
144 | else |
145 | str = msgSender; |
146 | |
147 | // qDebug() << "IgnoreListManager::match: "; |
148 | // qDebug() << "string: " << str; |
149 | // qDebug() << "pattern: " << ruleRx.pattern(); |
150 | // qDebug() << "scopeRule: " << item.scopeRule; |
151 | // qDebug() << "now testing"; |
152 | if ((!item.isRegEx && item.regEx.exactMatch(str)) || |
153 | (item.isRegEx && item.regEx.indexIn(str) != -1)) { |
154 | // qDebug() << "MATCHED!"; |
155 | return item.strictness; |
156 | } |
157 | } |
158 | } |
159 | return UnmatchedStrictness; |
160 | } |
161 | |
162 | |
163 | bool IgnoreListManager::scopeMatch(const QString &scopeRule, const QString &string) const |
164 | { |
165 | foreach(QString rule, scopeRule.split(";" )) { |
166 | QRegExp ruleRx = QRegExp(rule.trimmed()); |
167 | ruleRx.setCaseSensitivity(Qt::CaseInsensitive); |
168 | ruleRx.setPatternSyntax(QRegExp::Wildcard); |
169 | if (ruleRx.exactMatch(string)) { |
170 | return true; |
171 | } |
172 | } |
173 | return false; |
174 | } |
175 | |
176 | |
177 | void IgnoreListManager::removeIgnoreListItem(const QString &ignoreRule) |
178 | { |
179 | removeAt(indexOf(ignoreRule)); |
180 | SYNC(ARG(ignoreRule)) |
181 | } |
182 | |
183 | |
184 | void IgnoreListManager::toggleIgnoreRule(const QString &ignoreRule) |
185 | { |
186 | int idx = indexOf(ignoreRule); |
187 | if (idx == -1) |
188 | return; |
189 | _ignoreList[idx].isActive = !_ignoreList[idx].isActive; |
190 | SYNC(ARG(ignoreRule)) |
191 | } |
192 | |
193 | |
194 | bool IgnoreListManager::ctcpMatch(const QString sender, const QString &network, const QString &type) |
195 | { |
196 | foreach(IgnoreListItem item, _ignoreList) { |
197 | if (!item.isActive) |
198 | continue; |
199 | if (item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network))) { |
200 | QString sender_; |
201 | QStringList types = item.ignoreRule.split(QRegExp("\\s+" ), QString::SkipEmptyParts); |
202 | |
203 | sender_ = types.takeAt(0); |
204 | |
205 | QRegExp ruleRx = QRegExp(sender_); |
206 | ruleRx.setCaseSensitivity(Qt::CaseInsensitive); |
207 | if (!item.isRegEx) |
208 | ruleRx.setPatternSyntax(QRegExp::Wildcard); |
209 | if ((!item.isRegEx && ruleRx.exactMatch(sender)) || |
210 | (item.isRegEx && ruleRx.indexIn(sender) != -1)) { |
211 | if (types.isEmpty() || types.contains(type, Qt::CaseInsensitive)) |
212 | return true; |
213 | } |
214 | } |
215 | } |
216 | return false; |
217 | } |
218 | |