1 //=============================================================================
2 //
3 // File : KviNickServRuleSet.cpp
4 // Creation date : Thu Aug 09 2001 17:44:56 by Szymon Stefanek
5 //
6 // This file is part of the KVIrc IRC client distribution
7 // Copyright (C) 2001-2010 Szymon Stefanek (pragma at kvirc dot net)
8 //
9 // This program is FREE software. You can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the HOPE that it will be USEFUL,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 // See the GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24
25 #include "KviNickServRuleSet.h"
26 #include "KviConfigurationFile.h"
27 #include "KviIrcMask.h"
28 #include "KviQString.h"
29
30 #include <QRegExp>
31
32 /*
33 @doc: nickserv_proto
34 @title:
35 Authentication with NickServ
36 @keyterms:
37 NickServ, automatic authentication with NickServ
38 @type:
39 generic
40 @short:
41 Automatic authentication with NickServ
42 @body:
43 KVIrc supports automatic authentication with the NickServ service.[br]
44 This service is commonly implemented on major IRC networks: basically
45 it is a program that allows users to register their nickname and protect
46 it from being stolen by others.[br] The NickServ protocol is
47 not standardized (at the time that I'm writing this doc) and automatic
48 authentication is a pure experimental protocol.[br]
49 Once you get on IRC with a registered nickname, the NickServ will
50 ask you for identification by sending you a NOTICE.[br]
51 The message will look in a way similar to the following:[br]
52 <b>You're using a registered nickname: if this is your nick,
53 please type /msg NickServ IDENTIFY password, otherwise please
54 choose another nickname</b>.[br]
55 The message is often broken in two or three lines of text.[br]
56 Please note that many network policies suggest to avoid automatic authentication
57 with NickServ.[br]I have implemented it because I know that it works on the networks
58 that I'm usually on.[br]You have to check that this protocol works on your network and
59 then eventually use it at your own risk.[br]
60 */
61
62 // FIXME: The doc above is a bit outdated, fix it
63
KviNickServRuleSet()64 KviNickServRuleSet::KviNickServRuleSet()
65 : KviHeapObject()
66 {
67 m_bEnabled = false;
68 m_pRules = nullptr;
69 }
70
KviNickServRuleSet(const KviNickServRuleSet & s)71 KviNickServRuleSet::KviNickServRuleSet(const KviNickServRuleSet & s)
72 {
73 m_pRules = nullptr;
74 copyFrom(s);
75 }
76
~KviNickServRuleSet()77 KviNickServRuleSet::~KviNickServRuleSet()
78 {
79 if(m_pRules)
80 delete m_pRules;
81 }
82
save(KviConfigurationFile * pCfg,const QString & szPrefix)83 void KviNickServRuleSet::save(KviConfigurationFile * pCfg, const QString & szPrefix)
84 {
85 if(!m_pRules)
86 return; // nothing to save
87 if(m_pRules->isEmpty())
88 return; // should never happen anyway
89 QString szTmp;
90 if(m_bEnabled)
91 {
92 szTmp = QString("%1NSEnabled").arg(szPrefix);
93 pCfg->writeEntry(szTmp, m_bEnabled);
94 }
95 szTmp = QString("%1NSRules").arg(szPrefix);
96 pCfg->writeEntry(szTmp, m_pRules->count());
97 int i = 0;
98 for(KviNickServRule * pRule = m_pRules->first(); pRule; pRule = m_pRules->next())
99 {
100 szTmp = QString("%1NSRule%2_").arg(szPrefix).arg(i);
101 pRule->save(pCfg, szTmp);
102 i++;
103 }
104 }
105
load(KviConfigurationFile * pCfg,const QString & szPrefix)106 KviNickServRuleSet * KviNickServRuleSet::load(KviConfigurationFile * pCfg, const QString & szPrefix)
107 {
108 QString szTmp;
109 szTmp = QString("%1NSRules").arg(szPrefix);
110 unsigned int uCount = pCfg->readUIntEntry(szTmp, 0);
111 if(uCount == 0)
112 return nullptr;
113 KviNickServRuleSet * pSet = new KviNickServRuleSet();
114 if(pSet->loadPrivate(pCfg, szPrefix, uCount))
115 return pSet;
116 delete pSet;
117 return nullptr;
118 }
119
load(const QString & szConfigFile)120 void KviNickServRuleSet::load(const QString & szConfigFile)
121 {
122 clear();
123 KviConfigurationFile cfg(szConfigFile, KviConfigurationFile::Read);
124
125 QString szTmp = "NSRules";
126 unsigned int uCount = cfg.readUIntEntry(szTmp, 0);
127 if(uCount == 0)
128 return;
129 loadPrivate(&cfg, QString(""), uCount);
130 }
131
save(const QString & szConfigFile)132 void KviNickServRuleSet::save(const QString & szConfigFile)
133 {
134 KviConfigurationFile cfg(szConfigFile, KviConfigurationFile::Write);
135 cfg.clear();
136 save(&cfg, QString(""));
137 }
138
loadPrivate(KviConfigurationFile * pCfg,const QString & szPrefix,unsigned int uEntries)139 bool KviNickServRuleSet::loadPrivate(KviConfigurationFile * pCfg, const QString & szPrefix, unsigned int uEntries)
140 {
141 if(m_pRules)
142 m_pRules->clear();
143 else
144 {
145 m_pRules = new KviPointerList<KviNickServRule>;
146 m_pRules->setAutoDelete(true);
147 }
148
149 if(uEntries != 0)
150 {
151 QString szTmp;
152 szTmp = QString("%1NSEnabled").arg(szPrefix);
153 m_bEnabled = pCfg->readBoolEntry(szTmp, false);
154 for(unsigned int u = 0; u < uEntries; u++)
155 {
156 szTmp = QString("%1NSRule%2_").arg(szPrefix).arg(u);
157 KviNickServRule * pRule = new KviNickServRule();
158 if(!pRule->load(pCfg, szTmp))
159 delete pRule;
160 else
161 m_pRules->append(pRule);
162 }
163 }
164
165 if(m_pRules->isEmpty())
166 {
167 m_bEnabled = false;
168 delete m_pRules;
169 m_pRules = nullptr;
170 return false;
171 }
172 return true;
173 }
174
clear()175 void KviNickServRuleSet::clear()
176 {
177 if(m_pRules)
178 {
179 delete m_pRules;
180 m_pRules = nullptr;
181 }
182 m_bEnabled = false;
183 }
184
addRule(KviNickServRule * r)185 void KviNickServRuleSet::addRule(KviNickServRule * r)
186 {
187 if(!m_pRules)
188 {
189 m_pRules = new KviPointerList<KviNickServRule>;
190 m_pRules->setAutoDelete(true);
191 }
192 m_pRules->append(r);
193 }
194
createInstance()195 KviNickServRuleSet * KviNickServRuleSet::createInstance()
196 {
197 return new KviNickServRuleSet();
198 }
199
matchRule(const QString & szNick,const KviIrcMask * pNickServ,const QString & szMsg,const QString & szServer)200 KviNickServRule * KviNickServRuleSet::matchRule(const QString & szNick, const KviIrcMask * pNickServ, const QString & szMsg, const QString & szServer)
201 {
202 if(!m_pRules)
203 return nullptr;
204
205 for(KviNickServRule * r = m_pRules->first(); r; r = m_pRules->next())
206 {
207 if(!KviQString::matchString(r->registeredNick(), szNick, false, true))
208 continue;
209
210 if(!szServer.isEmpty())
211 {
212 QRegExp res(r->serverMask(), Qt::CaseInsensitive, QRegExp::Wildcard);
213 if(!res.exactMatch(szServer))
214 continue;
215 }
216 if(!pNickServ->matchedBy(KviIrcMask(r->nickServMask())))
217 continue;
218 QRegExp re(r->messageRegexp(), Qt::CaseInsensitive, QRegExp::Wildcard);
219 if(re.exactMatch(szMsg))
220 return r;
221 }
222 return nullptr;
223 }
224
copyFrom(const KviNickServRuleSet & src)225 void KviNickServRuleSet::copyFrom(const KviNickServRuleSet & src)
226 {
227 if(src.m_pRules)
228 {
229 if(m_pRules)
230 m_pRules->clear();
231 else
232 {
233 m_pRules = new KviPointerList<KviNickServRule>;
234 m_pRules->setAutoDelete(true);
235 }
236 for(KviNickServRule * r = src.m_pRules->first(); r; r = src.m_pRules->next())
237 {
238 KviNickServRule * c = new KviNickServRule();
239 c->copyFrom(*r);
240 m_pRules->append(c);
241 }
242 if(m_pRules->isEmpty())
243 {
244 m_bEnabled = false;
245 delete m_pRules;
246 m_pRules = nullptr;
247 }
248 else
249 {
250 m_bEnabled = src.m_bEnabled;
251 }
252 }
253 else
254 {
255 m_bEnabled = false;
256 if(m_pRules)
257 {
258 delete m_pRules;
259 m_pRules = nullptr;
260 }
261 }
262 }
263