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