1 //=============================================================================
2 //
3 //   File : KviIrcServer.cpp
4 //   Creation date : Mon Jul 10 2000 03:42:59 by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2000-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 "KviIrcServer.h"
26 #include "KviIrcServerReconnectInfo.h"
27 #include "KviMemory.h"
28 #include "KviConfigurationFile.h"
29 #include "KviNickServRuleSet.h"
30 #include "KviTimeUtils.h"
31 #include "KviProxyDataBase.h"
32 
33 #include <memory>
34 #include <vector>
35 #include <cstdlib>
36 
37 // This is not allowed on windows unless we force the symbol to be undefined
38 // It works on linux since gcc allows undefined symbols by default
39 // but it is also "theoretically" wrong:
40 //   kvilib is not linked to kvirc: it's kvirc being linked to kvilib
41 //   thus kvilib should not depend on symbols defined in the kvirc core.
42 // We must find another way to do that (like having just the id and finding
43 // the proxy in the kvirc core, or just passing the pointer to the db from outside).
44 //      Pragma
45 
46 //extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
47 
KviIrcServer()48 KviIrcServer::KviIrcServer()
49 {
50 	m_pReconnectInfo = nullptr;
51 	m_uFlags = Flags::CAP | Flags::STARTTLS;
52 	m_uPort = 6667;
53 	m_pAutoJoinChannelList = nullptr;
54 	m_bAutoConnect = false;
55 	m_iProxy = -1;
56 }
57 
proxyServer(KviProxyDataBase * pDb)58 KviProxy * KviIrcServer::proxyServer(KviProxyDataBase * pDb)
59 {
60 	int i = 0;
61 	if(proxy() < 0)
62 		return nullptr;
63 	std::vector<std::unique_ptr<KviProxy>> & proxylist = pDb->proxyList();
64 	for(auto & pProxy : proxylist)
65 	{
66 		if(i == proxy())
67 			return pProxy.get();
68 		i++;
69 	}
70 	return nullptr;
71 }
72 
KviIrcServer(const KviIrcServer & serv)73 KviIrcServer::KviIrcServer(const KviIrcServer & serv)
74 {
75 	m_szHostname = serv.m_szHostname;
76 	m_szIp = serv.m_szIp;
77 	m_szDescription = serv.m_szDescription;
78 	m_szUser = serv.m_szUser;
79 	m_szPass = serv.m_szPass;
80 	m_uPort = serv.m_uPort;
81 	m_szNick = serv.m_szNick;
82 	m_szAlternativeNick = serv.m_szAlternativeNick;
83 	m_szRealName = serv.m_szRealName;
84 	m_szEncoding = serv.m_szEncoding;
85 	m_szTextEncoding = serv.m_szTextEncoding;
86 	m_uFlags = serv.m_uFlags;
87 	m_szInitUMode = serv.m_szInitUMode;
88 	m_szOnConnectCommand = serv.m_szOnConnectCommand;
89 	m_szOnLoginCommand = serv.m_szOnLoginCommand;
90 	m_szLinkFilter = serv.m_szLinkFilter;
91 	m_szId = serv.m_szId;
92 	m_iProxy = serv.m_iProxy;
93 	m_szUserIdentityId = serv.m_szUserIdentityId;
94 	m_bAutoConnect = serv.m_bAutoConnect;
95 	m_szSaslNick = serv.m_szSaslNick;
96 	m_szSaslPass = serv.m_szSaslPass;
97 	m_szSaslMethod = serv.m_szSaslMethod;
98 
99 	if(serv.m_pAutoJoinChannelList)
100 		m_pAutoJoinChannelList = new QStringList(*(serv.m_pAutoJoinChannelList));
101 	else
102 		m_pAutoJoinChannelList = nullptr;
103 
104 	if(serv.m_pReconnectInfo)
105 		m_pReconnectInfo = new KviIrcServerReconnectInfo(*(serv.m_pReconnectInfo));
106 	else
107 		m_pReconnectInfo = nullptr;
108 }
109 
operator =(const KviIrcServer & serv)110 void KviIrcServer::operator=(const KviIrcServer & serv)
111 {
112 	m_szHostname = serv.m_szHostname;
113 	m_szIp = serv.m_szIp;
114 	m_szDescription = serv.m_szDescription;
115 	m_szUser = serv.m_szUser;
116 	m_szPass = serv.m_szPass;
117 	m_uPort = serv.m_uPort;
118 	m_szNick = serv.m_szNick;
119 	m_szAlternativeNick = serv.m_szAlternativeNick;
120 	m_szRealName = serv.m_szRealName;
121 	m_szEncoding = serv.m_szEncoding;
122 	m_szTextEncoding = serv.m_szTextEncoding;
123 	m_uFlags = serv.m_uFlags;
124 	m_szInitUMode = serv.m_szInitUMode;
125 	m_szOnConnectCommand = serv.m_szOnConnectCommand;
126 	m_szOnLoginCommand = serv.m_szOnLoginCommand;
127 	m_szLinkFilter = serv.m_szLinkFilter;
128 	m_szId = serv.m_szId;
129 	m_szUserIdentityId = serv.m_szUserIdentityId;
130 	m_iProxy = serv.m_iProxy;
131 	m_bAutoConnect = serv.m_bAutoConnect;
132 	m_szSaslNick = serv.m_szSaslNick;
133 	m_szSaslPass = serv.m_szSaslPass;
134 
135 	if(m_pAutoJoinChannelList)
136 		delete m_pAutoJoinChannelList;
137 	if(serv.m_pAutoJoinChannelList)
138 		m_pAutoJoinChannelList = new QStringList(*(serv.m_pAutoJoinChannelList));
139 	else
140 		m_pAutoJoinChannelList = nullptr;
141 
142 	if(m_pReconnectInfo)
143 		delete m_pReconnectInfo;
144 	if(serv.m_pReconnectInfo)
145 		m_pReconnectInfo = new KviIrcServerReconnectInfo(*(serv.m_pReconnectInfo));
146 	else
147 		m_pReconnectInfo = nullptr;
148 }
149 
~KviIrcServer()150 KviIrcServer::~KviIrcServer()
151 {
152 	if(m_pAutoJoinChannelList)
153 	{
154 		delete m_pAutoJoinChannelList;
155 		m_pAutoJoinChannelList = nullptr;
156 	}
157 	if(m_pReconnectInfo)
158 	{
159 		delete m_pReconnectInfo;
160 		m_pReconnectInfo = nullptr;
161 	}
162 }
163 
setReconnectInfo(KviIrcServerReconnectInfo * pInfo)164 void KviIrcServer::setReconnectInfo(KviIrcServerReconnectInfo * pInfo)
165 {
166 	if(m_pReconnectInfo)
167 		delete m_pReconnectInfo;
168 	m_pReconnectInfo = pInfo;
169 }
170 
clearReconnectInfo()171 void KviIrcServer::clearReconnectInfo()
172 {
173 	if(!m_pReconnectInfo)
174 		return;
175 	delete m_pReconnectInfo;
176 	m_pReconnectInfo = nullptr;
177 }
178 
generateUniqueId()179 void KviIrcServer::generateUniqueId()
180 {
181 	struct timeval tv;
182 	kvi_gettimeofday(&tv);
183 	m_szId = QString("myserver%1%2%3").arg(tv.tv_usec).arg(rand() % 1000).arg(rand() % 1000);
184 }
185 
ircUri()186 QString KviIrcServer::ircUri()
187 {
188 	QString szUri("irc");
189 	if(useSSL())
190 		szUri += "s";
191 	if(isIPv6())
192 		szUri += "6";
193 	szUri += "://";
194 	szUri += m_szHostname;
195 
196 	if(m_uPort != 6667)
197 	{
198 		szUri += ":";
199 		QString szNum;
200 		szNum.setNum(m_uPort);
201 		szUri += szNum;
202 	}
203 	return szUri;
204 }
205 
setAutoJoinChannelList(QStringList * pNewChannelList)206 void KviIrcServer::setAutoJoinChannelList(QStringList * pNewChannelList)
207 {
208 	if(m_pAutoJoinChannelList)
209 		delete m_pAutoJoinChannelList;
210 	m_pAutoJoinChannelList = pNewChannelList;
211 }
212 
setAutoJoinChannelList(const QString & szNewChannelList)213 void KviIrcServer::setAutoJoinChannelList(const QString & szNewChannelList)
214 {
215 	if(m_pAutoJoinChannelList)
216 		delete m_pAutoJoinChannelList;
217 	QStringList lChans = szNewChannelList.split(",");
218 	if(lChans.isEmpty())
219 		m_pAutoJoinChannelList = nullptr;
220 	else
221 		m_pAutoJoinChannelList = new QStringList(lChans);
222 }
223 
load(KviConfigurationFile * pCfg,const QString & szPrefix)224 bool KviIrcServer::load(KviConfigurationFile * pCfg, const QString & szPrefix)
225 {
226 	QString szTmp;
227 	szTmp = QString("%1Hostname").arg(szPrefix);
228 	m_szHostname = pCfg->readEntry(szTmp);
229 	szTmp = QString("%1Ip").arg(szPrefix);
230 	m_szIp = pCfg->readEntry(szTmp);
231 	if(m_szHostname.isEmpty() && m_szIp.isEmpty())
232 		return false;
233 
234 	szTmp = QString("%1Description").arg(szPrefix);
235 	m_szDescription = pCfg->readEntry(szTmp);
236 	szTmp = QString("%1User").arg(szPrefix);
237 	m_szUser = pCfg->readEntry(szTmp);
238 	szTmp = QString("%1Pass").arg(szPrefix);
239 	m_szPass = pCfg->readEntry(szTmp);
240 	szTmp = QString("%1Nick").arg(szPrefix);
241 	m_szNick = pCfg->readEntry(szTmp);
242 	szTmp = QString("%1AlternativeNick").arg(szPrefix);
243 	m_szAlternativeNick = pCfg->readEntry(szTmp);
244 	szTmp = QString("%1SaslPass").arg(szPrefix);
245 	m_szSaslPass = pCfg->readEntry(szTmp);
246 	szTmp = QString("%1SaslNick").arg(szPrefix);
247 	m_szSaslNick = pCfg->readEntry(szTmp);
248 	szTmp = QString("%1SaslMethod").arg(szPrefix);
249 	m_szSaslMethod = pCfg->readEntry(szTmp, QStringLiteral("PLAIN"));
250 	szTmp = QString("%1RealName").arg(szPrefix);
251 	m_szRealName = pCfg->readEntry(szTmp);
252 	szTmp = QString("%1InitUmode").arg(szPrefix);
253 	m_szInitUMode = pCfg->readEntry(szTmp);
254 	szTmp = QString("%1AutoJoinChannels").arg(szPrefix);
255 	QStringList l = pCfg->readStringListEntry(szTmp, QStringList());
256 	if(l.count() > 0)
257 		setAutoJoinChannelList(new QStringList(l));
258 
259 	szTmp = QString("%1AutoConnect").arg(szPrefix);
260 	m_bAutoConnect = pCfg->readBoolEntry(szTmp, false);
261 	szTmp = QString("%1Encoding").arg(szPrefix);
262 	m_szEncoding = pCfg->readEntry(szTmp);
263 	szTmp = QString("%1TextEncoding").arg(szPrefix);
264 	m_szTextEncoding = pCfg->readEntry(szTmp);
265 	szTmp = QString("%1OnConnectCommand").arg(szPrefix);
266 	m_szOnConnectCommand = pCfg->readEntry(szTmp);
267 	szTmp = QString("%1OnLoginCommand").arg(szPrefix);
268 	m_szOnLoginCommand = pCfg->readEntry(szTmp);
269 	szTmp = QString("%1LinkFilter").arg(szPrefix);
270 	m_szLinkFilter = pCfg->readEntry(szTmp);
271 	szTmp = QString("%1Port").arg(szPrefix);
272 	m_uPort = pCfg->readUIntEntry(szTmp, 6667);
273 	szTmp = QString("%1Id").arg(szPrefix);
274 	m_szId = pCfg->readEntry(szTmp);
275 	if(m_szId.isEmpty())
276 		generateUniqueId();
277 
278 	szTmp = QString("%1IPv6").arg(szPrefix);
279 	setIPv6(pCfg->readBoolEntry(szTmp, false));
280 	szTmp = QString("%1CacheIp").arg(szPrefix);
281 	setCacheIp(pCfg->readBoolEntry(szTmp, false)); // true ?
282 	szTmp = QString("%1SSL").arg(szPrefix);
283 	setUseSSL(pCfg->readBoolEntry(szTmp, false));
284 	szTmp = QString("%1EnabledCAP").arg(szPrefix);
285 	setEnabledCAP(pCfg->readBoolEntry(szTmp, true));
286 	szTmp = QString("%1EnabledSTARTTLS").arg(szPrefix);
287 	setEnabledSTARTTLS(pCfg->readBoolEntry(szTmp, true));
288 	szTmp = QString("%1EnabledSASL").arg(szPrefix);
289 	setEnabledSASL(pCfg->readBoolEntry(szTmp, false));
290 	szTmp = QString("%1Proxy").arg(szPrefix);
291 	setProxy(pCfg->readIntEntry(szTmp, -2));
292 	szTmp = QString("%1UserIdentityId").arg(szPrefix);
293 	m_szUserIdentityId = pCfg->readEntry(szTmp);
294 	szTmp = QString("%1Favorite").arg(szPrefix);
295 	setFavorite(pCfg->readBoolEntry(szTmp, false));
296 	return true;
297 }
298 
save(KviConfigurationFile * pCfg,const QString & szPrefix)299 void KviIrcServer::save(KviConfigurationFile * pCfg, const QString & szPrefix)
300 {
301 	QString szTmp;
302 	szTmp = QString("%1Hostname").arg(szPrefix);
303 	pCfg->writeEntry(szTmp, m_szHostname);
304 	szTmp = QString("%1Id").arg(szPrefix);
305 	pCfg->writeEntry(szTmp, m_szId);
306 	if(!m_szIp.isEmpty())
307 	{
308 		szTmp = QString("%1Ip").arg(szPrefix);
309 		pCfg->writeEntry(szTmp, m_szIp);
310 	}
311 	if(!m_szDescription.isEmpty())
312 	{
313 		szTmp = QString("%1Description").arg(szPrefix);
314 		pCfg->writeEntry(szTmp, m_szDescription);
315 	}
316 	if(!m_szUser.isEmpty())
317 	{
318 		szTmp = QString("%1User").arg(szPrefix);
319 		pCfg->writeEntry(szTmp, m_szUser);
320 	}
321 	if(!m_szPass.isEmpty())
322 	{
323 		szTmp = QString("%1Pass").arg(szPrefix);
324 		pCfg->writeEntry(szTmp, m_szPass);
325 	}
326 	if(!m_szNick.isEmpty())
327 	{
328 		szTmp = QString("%1Nick").arg(szPrefix);
329 		pCfg->writeEntry(szTmp, m_szNick);
330 	}
331 	if(!m_szAlternativeNick.isEmpty())
332 	{
333 		szTmp = QString("%1AlternativeNick").arg(szPrefix);
334 		pCfg->writeEntry(szTmp, m_szAlternativeNick);
335 	}
336 	if(!m_szSaslPass.isEmpty())
337 	{
338 		szTmp = QString("%1SaslPass").arg(szPrefix);
339 		pCfg->writeEntry(szTmp, m_szSaslPass);
340 	}
341 	if(!m_szSaslNick.isEmpty())
342 	{
343 		szTmp = QString("%1SaslNick").arg(szPrefix);
344 		pCfg->writeEntry(szTmp, m_szSaslNick);
345 	}
346 	if(!m_szSaslMethod.isEmpty() && enabledSASL())
347 	{
348 		szTmp = QString("%1SaslMethod").arg(szPrefix);
349 		pCfg->writeEntry(szTmp, m_szSaslMethod);
350 	}
351 	if(!m_szRealName.isEmpty())
352 	{
353 		szTmp = QString("%1RealName").arg(szPrefix);
354 		pCfg->writeEntry(szTmp, m_szRealName);
355 	}
356 	if(!m_szInitUMode.isEmpty())
357 	{
358 		szTmp = QString("%1InitUMode").arg(szPrefix);
359 		pCfg->writeEntry(szTmp, m_szInitUMode);
360 	}
361 	if(autoJoinChannelList())
362 	{
363 		szTmp = QString("%1AutoJoinChannels").arg(szPrefix);
364 		pCfg->writeEntry(szTmp, *(autoJoinChannelList()));
365 	}
366 	if(autoConnect()) // otherwise it defaults to false anyway
367 	{
368 		szTmp = QString("%1AutoConnect").arg(szPrefix);
369 		pCfg->writeEntry(szTmp, autoConnect());
370 	}
371 	if(!m_szEncoding.isEmpty())
372 	{
373 		szTmp = QString("%1Encoding").arg(szPrefix);
374 		pCfg->writeEntry(szTmp, m_szEncoding);
375 	}
376 	if(!m_szTextEncoding.isEmpty())
377 	{
378 		szTmp = QString("%1TextEncoding").arg(szPrefix);
379 		pCfg->writeEntry(szTmp, m_szTextEncoding);
380 	}
381 	if(!m_szOnConnectCommand.isEmpty())
382 	{
383 		szTmp = QString("%1OnConnectCommand").arg(szPrefix);
384 		pCfg->writeEntry(szTmp, m_szOnConnectCommand);
385 	}
386 	if(!m_szOnLoginCommand.isEmpty())
387 	{
388 		szTmp = QString("%1OnLoginCommand").arg(szPrefix);
389 		pCfg->writeEntry(szTmp, m_szOnLoginCommand);
390 	}
391 	if(!m_szLinkFilter.isEmpty())
392 	{
393 		szTmp = QString("%1LinkFilter").arg(szPrefix);
394 		pCfg->writeEntry(szTmp, m_szLinkFilter);
395 	}
396 	if(m_uPort != 6667)
397 	{
398 		szTmp = QString("%1Port").arg(szPrefix);
399 		pCfg->writeEntry(szTmp, m_uPort);
400 	}
401 	if(isIPv6())
402 	{
403 		szTmp = QString("%1IPv6").arg(szPrefix);
404 		pCfg->writeEntry(szTmp, isIPv6());
405 	}
406 	if(cacheIp())
407 	{
408 		szTmp = QString("%1CacheIp").arg(szPrefix);
409 		pCfg->writeEntry(szTmp, cacheIp());
410 	}
411 	if(useSSL())
412 	{
413 		szTmp = QString("%1SSL").arg(szPrefix);
414 		pCfg->writeEntry(szTmp, useSSL());
415 	}
416 	if(!enabledCAP())
417 	{
418 		szTmp = QString("%1EnabledCAP").arg(szPrefix);
419 		pCfg->writeEntry(szTmp, enabledCAP());
420 	}
421 	if(!enabledSTARTTLS())
422 	{
423 		szTmp = QString("%1EnabledSTARTTLS").arg(szPrefix);
424 		pCfg->writeEntry(szTmp, enabledSTARTTLS());
425 	}
426 	if(enabledSASL())
427 	{
428 		szTmp = QString("%1EnabledSASL").arg(szPrefix);
429 		pCfg->writeEntry(szTmp, enabledSASL());
430 	}
431 	if(proxy() != -2)
432 	{
433 		szTmp = QString("%1Proxy").arg(szPrefix);
434 		pCfg->writeEntry(szTmp, proxy());
435 	}
436 	if(!m_szUserIdentityId.isEmpty())
437 	{
438 		szTmp = QString("%1UserIdentityId").arg(szPrefix);
439 		pCfg->writeEntry(szTmp, m_szUserIdentityId);
440 	}
441 	if(favorite())
442 	{
443 		szTmp = QString("%1Favorite").arg(szPrefix);
444 		pCfg->writeEntry(szTmp, favorite());
445 	}
446 }
447