summaryrefslogtreecommitdiffstats
path: root/src/kvilib/irc
diff options
context:
space:
mode:
Diffstat (limited to 'src/kvilib/irc')
-rw-r--r--src/kvilib/irc/Makefile.am5
-rw-r--r--src/kvilib/irc/kvi_avatar.cpp165
-rw-r--r--src/kvilib/irc/kvi_avatar.h83
-rw-r--r--src/kvilib/irc/kvi_avatarcache.cpp250
-rw-r--r--src/kvilib/irc/kvi_avatarcache.h69
-rw-r--r--src/kvilib/irc/kvi_ircmask.cpp760
-rw-r--r--src/kvilib/irc/kvi_ircmask.h164
-rw-r--r--src/kvilib/irc/kvi_ircserver.cpp373
-rw-r--r--src/kvilib/irc/kvi_ircserver.h206
-rw-r--r--src/kvilib/irc/kvi_ircserverdb.cpp646
-rw-r--r--src/kvilib/irc/kvi_ircserverdb.h116
-rw-r--r--src/kvilib/irc/kvi_ircuserdb.cpp285
-rw-r--r--src/kvilib/irc/kvi_ircuserdb.h145
-rw-r--r--src/kvilib/irc/kvi_mirccntrl.cpp307
-rw-r--r--src/kvilib/irc/kvi_mirccntrl.h163
-rw-r--r--src/kvilib/irc/kvi_nickserv.cpp312
-rw-r--r--src/kvilib/irc/kvi_nickserv.h112
-rw-r--r--src/kvilib/irc/kvi_useridentity.cpp252
-rw-r--r--src/kvilib/irc/kvi_useridentity.h145
-rw-r--r--src/kvilib/irc/moc_kvi_ircuserdb.cpp119
20 files changed, 4677 insertions, 0 deletions
diff --git a/src/kvilib/irc/Makefile.am b/src/kvilib/irc/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvilib/irc/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvilib/irc/kvi_avatar.cpp b/src/kvilib/irc/kvi_avatar.cpp
new file mode 100644
index 00000000..1642560a
--- /dev/null
+++ b/src/kvilib/irc/kvi_avatar.cpp
@@ -0,0 +1,165 @@
+//=============================================================================
+//
+// File : kvi_avatar.cpp
+// Creation date : Fri Dec 01 2000 13:58:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+#define __KVILIB__
+
+
+#include "kvi_avatar.h"
+#include "kvi_qstring.h"
+
+#include <qimage.h>
+
+
+/*
+ @doc: ctcp_avatar
+ @title:
+ The AVATAR idea
+ @short:
+ Extending IRC fun: the AVATAR idea
+ @body:
+ [big]Introduction[/big]
+ Starting from version 3.0.0 KVIrc supports the AVATAR protocol.
+ The AVATAR term dictionary definitions include:[br]
+ - Hindu mythology incarnation of a God[br]
+ - Embodiment of a concept or philosophy[br]
+ - In [b]cyberspace communities[/b], the rappresentation of an
+ user in a shared virtual reality.[br]
+ The AVATAR protocol attempts to improve the IRC communication
+ by adding a method for associating a graphical rappresentation
+ to an IRC user.[br]
+ Since this may involve binary data transfers between users,
+ the protocol is intended to be client based.
+ [big]The terms[/big]
+ The user that wants to offer a digital rappresentation of himself
+ will be called "source user". The ones that will receive the notification
+ will be called "target users".
+ Every irc user can be either a source user or target user.
+ [big]The idea[/big]
+ Every irc user has a client-side property called AVATAR. Let's say that there
+ are two users: A and B.[br]
+ When user A wants to see the B's avatar he simply sends a CTCP AVATAR request
+ to B (the request is sent through a PRIVMSG irc command).[br]
+ User B replies with a CTCP AVATAR notification (sent through a NOTICE irc command)
+ with the name or url of his avatar.[br]
+ The actual syntax for the notification is:[br]
+ [b]AVATAR <avatar_file> [<filesize>][/b]
+ The <avatar_file> may be either the name of a B's local image file or an url
+ pointing to an image on some web server.[br]
+ The optional <filesize> parameter is sent only if <avatar_file> is
+ stored on the B's machine and there will be more info on that later.[br]
+ Anyway, after A has received the notification he tries to locate the avatar
+ file in its local cache (yes, <filesize> may help here and more on this later).
+ If the file can be found
+ and loaded then it is simply displayed in some way near the B's nickname
+ otherwise A must download the avatar from some place.
+ If the <avatar_file> contains a leading url prefix (http://) then
+ A fetches the image from the specified url and after that displays
+ it near the B's nickname. If the <avatar_file> does not contain the
+ leading url prefix then it is assumed that B offers this file for
+ downloading via DCC from his machine. In this case A may also avoid
+ requesting the file if the <filesize> is too large and the transfer
+ would occupy too much bandwidth (for example).
+ The DCC download is initiated by issuing a DCC GET <avatar_file> request to B.
+ B may then reply with a standard DCC SEND or a DCC RSEND (kvirc's extension).[br]
+ The implementation of the DCC GET protocol is defined by other documents here around :).[br]
+ [br]
+ The CTCP AVATAR messages can be sent to a single user , a set of users or a channel:
+ this depends only on the source user and how many clients he wants to reach.
+ [br]
+ There should be a convention on the image sizes: not a protocol limit.
+ For example, the convention could be that all the images should be smaller than
+ 129x129 pixels. The preferred image format is "png" (Portable Network Graphics)
+ since it allows good compression rates without compromising the image quality.
+ Other formats may be accepted as well (Theoretically this protocol could be
+ extended to allow movies or 3D images).
+ The "preferred" image size may grow with time, as the network transmission speed grows.
+*/
+
+KviAvatar::KviAvatar(const QString &szLocalPath,const QString &szName,QPixmap * pix)
+{
+ m_pPixmap = pix;
+ m_pScaledPixmap = 0;
+ if(m_pPixmap == 0)m_pPixmap = new QPixmap(32,32); // cool memory map :)
+
+ m_bRemote = KviQString::equalCIN("http://",szName,7);
+
+ m_szLocalPath = szLocalPath;
+ m_szName = szName;
+}
+
+KviAvatar::~KviAvatar()
+{
+ delete m_pPixmap;
+ if(m_pScaledPixmap)delete m_pScaledPixmap;
+}
+
+QPixmap * KviAvatar::scaledPixmap(unsigned int w,unsigned int h)
+{
+ if(((unsigned int)(m_pPixmap->width())) == w)
+ {
+ if(((unsigned int)(m_pPixmap->height())) == h)
+ return m_pPixmap;
+ }
+
+ if(m_pScaledPixmap)
+ {
+ if((m_uLastScaleWidth == w) && (m_uLastScaleHeight == h))return m_pScaledPixmap;
+ delete m_pScaledPixmap;
+ m_pScaledPixmap = 0;
+ }
+
+ int curW = m_pPixmap->width();
+ int curH = m_pPixmap->height();
+
+ if(curW < 1)curW = 1;
+ if(curH < 1)curH = 1;
+
+ m_uLastScaleWidth = w;
+ m_uLastScaleHeight = h;
+
+ int scaleW = w;
+ int scaleH;
+
+ /* We want to maintain the aspect of the image instead simply set
+ height and width. The first step is trying to adapt the image size
+ by "w" vaule */
+
+ scaleH = (curH * scaleW) / curW;
+
+ /* Now check the resized image size. If it is too wide or too tall,
+ resize it again by "h" value */
+ if(scaleH > h) {
+ scaleH = h;
+ scaleW = (scaleH * curW) / curH;
+ }
+
+#ifdef COMPILE_USE_QT4
+ m_pScaledPixmap = new QPixmap(m_pPixmap->scaled(scaleW,scaleH));
+#else
+ QImage img = m_pPixmap->convertToImage();
+
+ m_pScaledPixmap = new QPixmap();
+ m_pScaledPixmap->convertFromImage(img.smoothScale(scaleW,scaleH));
+#endif
+ return m_pScaledPixmap;
+}
diff --git a/src/kvilib/irc/kvi_avatar.h b/src/kvilib/irc/kvi_avatar.h
new file mode 100644
index 00000000..ba8edbc5
--- /dev/null
+++ b/src/kvilib/irc/kvi_avatar.h
@@ -0,0 +1,83 @@
+#ifndef _KVI_AVATAR_H_
+#define _KVI_AVATAR_H_
+
+//=============================================================================
+//
+// File : kvi_avatar.h
+// Creation date : Fri Dec 01 2000 13:54:04 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "kvi_string.h"
+#include "kvi_heapobject.h"
+#include "kvi_settings.h"
+
+#include <qpixmap.h>
+
+class KVILIB_API KviAvatar : public KviHeapObject
+{
+public:
+ KviAvatar(const QString &szLocalPath,const QString &szName,QPixmap * pix);
+ ~KviAvatar();
+private:
+ QString m_szLocalPath;
+ QString m_szName;
+ bool m_bRemote;
+
+ QPixmap * m_pPixmap;
+ QPixmap * m_pScaledPixmap;
+
+ unsigned int m_uLastScaleWidth;
+ unsigned int m_uLastScaleHeight;
+public:
+ QPixmap * pixmap(){ return m_pPixmap; };
+ QPixmap * scaledPixmap(unsigned int w,unsigned int h);
+
+ bool isRemote(){ return m_bRemote; };
+
+ const QString &localPath(){ return m_szLocalPath; };
+ const QString &name(){ return m_szName; };
+
+ // string that uniquely identifies this avatar
+ // for remote avatars that have name starting with http://
+ // the name is used.
+ // for local avatars the localPath is used instead
+ const QString &identificationString(){ return m_bRemote ? m_szName : m_szLocalPath; };
+
+
+ // if name is http://xxxx
+ // then identification is the name
+ // if name is xxx.png
+ // then identification is the local path
+
+
+ // name : visible name of the avatar : url or filename
+ // ex: http://www.kvirc.net/img/pragma.png
+ // ex: pragma.png
+ // local path : local path
+ // ex: /home/pragma/.kvirc/avatars/http.www.kvirc.net.img.pragma.png
+ // ex: /home/pragma/.kvirc/avatars/pragma.png
+
+ // local path->name : strip leading path informations
+ // name->local path : replace : / and
+
+};
+
+#endif //_KVI_AVATAR_H_
diff --git a/src/kvilib/irc/kvi_avatarcache.cpp b/src/kvilib/irc/kvi_avatarcache.cpp
new file mode 100644
index 00000000..d24562ea
--- /dev/null
+++ b/src/kvilib/irc/kvi_avatarcache.cpp
@@ -0,0 +1,250 @@
+//=============================================================================
+//
+// File : kvi_avatarcache.cpp
+// Created on Sat 27 Dec 2003 21:19:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot net>
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+#define __KVILIB__
+
+
+#include "kvi_avatarcache.h"
+#include "kvi_pointerlist.h"
+#include "kvi_config.h"
+
+// this level triggers a cleanup
+#define MAX_AVATARS_IN_CACHE 100
+// this is the level that has be reached by a cleanup
+#define CACHE_GUARD_LEVEL 85
+// dictionary size
+#define CACHE_DICT_SIZE 101
+// keep the unaccessed avatars for 30 days
+#define MAX_UNACCESSED_TIME (3600 * 24 * 30)
+
+
+KviAvatarCache * KviAvatarCache::m_pAvatarCacheInstance = 0;
+
+void KviAvatarCache::init()
+{
+ if(m_pAvatarCacheInstance)
+ {
+ debug("WARNING: trying to initialize the avatar cache twice");
+ return;
+ }
+
+ m_pAvatarCacheInstance = new KviAvatarCache();
+}
+
+void KviAvatarCache::done()
+{
+ if(!m_pAvatarCacheInstance)
+ {
+ debug("WARNING: trying to destroy an uninitialized avatar cache");
+ return;
+ }
+
+ delete m_pAvatarCacheInstance;
+ m_pAvatarCacheInstance = 0;
+}
+
+
+KviAvatarCache::KviAvatarCache()
+{
+ m_pAvatarDict = new KviPointerHashTable<QString,KviAvatarCacheEntry>(CACHE_DICT_SIZE,false);
+ m_pAvatarDict->setAutoDelete(true);
+}
+
+KviAvatarCache::~KviAvatarCache()
+{
+ delete m_pAvatarDict;
+}
+
+
+void KviAvatarCache::replace(const QString &szIdString,const KviIrcMask &mask,const QString &szNetwork)
+{
+ QString szKey;
+
+ mask.mask(szKey,KviIrcMask::NickCleanUserSmartNet);
+ szKey.append(QChar('+'));
+ szKey.append(szNetwork);
+
+ KviAvatarCacheEntry * e = new KviAvatarCacheEntry;
+ e->szIdString = szIdString;
+ e->tLastAccess = kvi_unixTime();
+
+ m_pAvatarDict->replace(szKey,e);
+
+ if(m_pAvatarDict->count() > MAX_AVATARS_IN_CACHE)
+ {
+ cleanup();
+ }
+}
+
+void KviAvatarCache::remove(const KviIrcMask &mask,const QString &szNetwork)
+{
+ QString szKey;
+
+ mask.mask(szKey,KviIrcMask::NickCleanUserSmartNet);
+ szKey.append(QChar('+'));
+ szKey.append(szNetwork);
+
+ m_pAvatarDict->remove(szKey);
+}
+
+
+
+const QString & KviAvatarCache::lookup(const KviIrcMask &mask,const QString &szNetwork)
+{
+ QString szKey;
+
+ mask.mask(szKey,KviIrcMask::NickCleanUserSmartNet);
+ szKey.append(QChar('+'));
+ szKey.append(szNetwork);
+
+ KviAvatarCacheEntry * e = m_pAvatarDict->find(szKey);
+ if(!e)return KviQString::empty;
+ e->tLastAccess = kvi_unixTime();
+ return e->szIdString;
+}
+
+void KviAvatarCache::load(const QString &szFileName)
+{
+ m_pAvatarDict->clear();
+
+ KviConfig cfg(szFileName,KviConfig::Read);
+
+ kvi_time_t tNow = kvi_unixTime();
+
+ KviConfigIterator it(*(cfg.dict()));
+
+ int cnt = 0;
+
+ while(it.current())
+ {
+ cfg.setGroup(it.currentKey());
+
+ kvi_time_t tLastAccess = cfg.readUIntEntry("LastAccess",0);
+ if((tNow - tLastAccess) < MAX_UNACCESSED_TIME)
+ {
+ QString szIdString = cfg.readQStringEntry("Avatar","");
+
+ if(!szIdString.isEmpty())
+ {
+ KviAvatarCacheEntry * e = new KviAvatarCacheEntry;
+ e->tLastAccess = tLastAccess;
+ e->szIdString = szIdString;
+ m_pAvatarDict->replace(it.currentKey(),e);
+ cnt++;
+ if(cnt >= MAX_AVATARS_IN_CACHE)return; // done
+ }
+ }
+ ++it;
+ }
+}
+
+void KviAvatarCache::save(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+// cfg.clear(); // not needed with KviConfig::Write
+
+ KviPointerHashTableIterator<QString,KviAvatarCacheEntry> it(*m_pAvatarDict);
+
+ while(KviAvatarCacheEntry * e = it.current())
+ {
+ if(e->tLastAccess)
+ {
+ cfg.setGroup(it.currentKey());
+ cfg.writeEntry("Avatar",e->szIdString);
+ cfg.writeEntry("LastAccess",((unsigned int)(e->tLastAccess)));
+ }
+ ++it;
+ }
+}
+
+void KviAvatarCache::cleanup()
+{
+ // first do a quick run deleting the avatars really too old
+ KviPointerHashTableIterator<QString,KviAvatarCacheEntry> it(*m_pAvatarDict);
+
+ kvi_time_t tNow = kvi_unixTime();
+
+ KviPointerList<QString> l;
+ l.setAutoDelete(false);
+
+ KviAvatarCacheEntry * e;
+
+ while((e = it.current()))
+ {
+ if((tNow - e->tLastAccess) > MAX_UNACCESSED_TIME)
+ {
+ l.append(new QString(it.currentKey()));
+ }
+ ++it;
+ }
+
+ for(QString *s = l.first();s;s = l.next())m_pAvatarDict->remove(*s);
+
+ if(m_pAvatarDict->count() < CACHE_GUARD_LEVEL)return;
+
+ // not done.. need to kill the last accessed :/
+
+ it.toFirst();
+
+ KviPointerList<KviAvatarCacheEntry> ll;
+ ll.setAutoDelete(true);
+
+ // here we use the cache entries in another way
+ // szAvatar is the KEY instead of the avatar name
+
+ while((e = it.current()))
+ {
+ KviAvatarCacheEntry * current = ll.first();
+ unsigned int idx = 0;
+ while(current)
+ {
+ // if the current is newer than the inserted one
+ // then stop searching and insert it just before
+ if(current->tLastAccess > e->tLastAccess)break;
+ // otherwise the current is older and the inserted
+ // one goes after
+ current = ll.next();
+ idx++;
+ }
+
+ KviAvatarCacheEntry * xx = new KviAvatarCacheEntry;
+ xx->szIdString = it.currentKey();
+ xx->tLastAccess = e->tLastAccess;
+
+ if(current)ll.insert(idx,xx);
+ else ll.append(xx);
+ ++it;
+ }
+
+ // the oldest keys are at the beginning
+ int uRemove = ll.count() - CACHE_GUARD_LEVEL;
+ if(uRemove < 1)return; // huh ?
+
+ // remember that szAvatar contains the key!
+ for(e = ll.first();e && (uRemove > 0);e = ll.next())
+ {
+ m_pAvatarDict->remove(e->szIdString);
+ uRemove--;
+ }
+ // now we should be ok
+}
diff --git a/src/kvilib/irc/kvi_avatarcache.h b/src/kvilib/irc/kvi_avatarcache.h
new file mode 100644
index 00000000..7d715256
--- /dev/null
+++ b/src/kvilib/irc/kvi_avatarcache.h
@@ -0,0 +1,69 @@
+#ifndef _KVI_AVATARCACHE_H_
+#define _KVI_AVATARCACHE_H_
+//=============================================================================
+//
+// File : kvi_avatarcache.h
+// Created on Sat 27 Dec 2003 21:19:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot net>
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_time.h"
+#include "kvi_ircmask.h"
+
+#include "kvi_pointerhashtable.h"
+
+
+typedef struct _KviAvatarCacheEntry
+{
+ QString szIdString;
+ kvi_time_t tLastAccess;
+} KviAvatarCacheEntry;
+
+
+
+class KVILIB_API KviAvatarCache
+{
+protected:
+ KviAvatarCache();
+ ~KviAvatarCache();
+public:
+ KviPointerHashTable<QString,KviAvatarCacheEntry> * m_pAvatarDict;
+protected:
+ static KviAvatarCache * m_pAvatarCacheInstance;
+public:
+ static void init();
+ static void done();
+
+ static KviAvatarCache * instance(){ return m_pAvatarCacheInstance; };
+
+ void replace(const QString &szIdString,const KviIrcMask &mask,const QString &szNetwork);
+ void remove(const KviIrcMask &mask,const QString &szNetwork);
+ const QString & lookup(const KviIrcMask &mask,const QString &szNetwork);
+
+ void cleanup();
+
+ void load(const QString &szFileName);
+ void save(const QString &szFileName);
+};
+
+
+#endif //!_KVI_AVATARCACHE_H_
diff --git a/src/kvilib/irc/kvi_ircmask.cpp b/src/kvilib/irc/kvi_ircmask.cpp
new file mode 100644
index 00000000..dbdc1b6c
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircmask.cpp
@@ -0,0 +1,760 @@
+//=============================================================================
+//
+// File : kvi_ircuser.cpp
+// Creation date : Fri Jan 8 1999 20:56:07 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_debug.h"
+#include "kvi_ircmask.h"
+
+/*
+ @doc: irc_masks
+ @title:
+ Irc masks
+ @type:
+ generic
+ @short:
+ Decription of the standard IRC masks
+ @keyterms:
+ irc masks , nickname , username , hostname , wildcard
+ @body:
+ [big]Simple masks[/big][br]
+ An irc mask is a string in a special format that identifies an user on irc.[br]
+ The standard basic format is:[br]
+ [b]<nick>!<username>@<host>[/b][br]
+ The <nick> part contains the nickname with that the user is widely known across the network.[br]
+ The nickname format is generally restricted by the irc network rules: usually it has a maximum
+ length (9 on actual IrcNet servers for example), and can contain only a defined set of characters.
+ Just as example, the character '!' obviously can't be included in a nickname.[br]
+ The <username> part is the machine username of the remote user: this is usually
+ retrieved by the irc server at connect time by contacting the ident service on the user's machine.
+ Some IRC servers allow specifying this username inside the login messages and do not connect
+ to the ident service at all.[br]
+ The <username> often has a special prefix character added by the irc server:[br]
+ this is rather server specific protocol , but the prefixes are somewhat standardized and
+ the common meanings of them are:[br]
+ noprefix: I line with ident[br]
+ ^: I line with OTHER type ident[br]
+ ~: I line, no ident[br]
+ +: i line with ident[br]
+ =: i line with OTHER type ident[br]
+ -: i line, no ident[br]
+ So finally you can find <username> strings like "~pragma" or "^pragma", where "pragma"
+ is the system username of the irc-user and ~ and ^ are prefixes.[br]
+ The <host> part is the hostname of the remote user.[br]
+ In most cases it is the human-readable format of the host name, but sometimes
+ it happens to be an IP-address (when the host has no reverse dns entry).[br]
+ The IP address can be either in IPV4 format or in IPV6 format.[br]
+ Some (weird from my point of view) servers hide certain parts of the IP address to
+ prevent attacks to the user's machine.[br]
+ Here are some examples of full irc-masks:[br]
+ Pragma!^pragma@staff.kvirc.net[br]
+ [jazz]!~jazz@jazz.myhome.com[br]
+ luke!=skywalker@212.213.41.12[br]
+ HAN!^solo@ff0f:a0a0:1011::ea80:1[br]
+ Darth!vader@210.11.12.XXX[br]
+ The irc-masks are [b]case insensitive[/b].[br]
+ [br]
+ [big]Wildcard masks[/big][br]
+ In some contexts the irc-masks can contain '*' and '?' wildcards.[br]
+ The wild masks are used to "match" an user within a set of them.[br]
+ '*' matches any sequence (eventually empty) of characters and '?' matches a single character.[br]
+ Wildcards are allowed only in the <nick> , <user> and <host> part: so the
+ "wildest" mask possible is:[br]
+ [b]*!*@*[/b][br]
+ that designates "any nickname, any username on any host".[br]
+ Here are some examples of wild masks:[br]
+ Pragma!*pragma@212.101.102.*: matches any user with nickname "Pragma" , username that ends with "pragma" and
+ coming from any machine on the 212.101.102 network.[br]
+ *!solo@*.starwars.org: matches any nick with username solo (no prefix!) coming from any machine in
+ the starwars.org domain.[br]
+ Pragma!*@*: matches any user with nickname "Pragma".[br]
+*/
+
+/*
+const char * KviIrcMask::setMask(const char *szMask,char c)
+{
+ __range_valid(szMask);
+ //nick!username@host.top
+ //0123456789
+ register const char *p=szMask;
+ //Run over nick....
+ while(*p && (*p != '!'))p++;
+ int len = p - szMask;
+ if(len > 0){
+ m_nick_ptr = (char *)kvi_realloc(m_nick_ptr,len+1);
+ kvi_memmove((void *)m_nick_ptr,(void *)szMask,len);
+ } else { //Empty nick...set it to "*"
+ len = 1;
+ m_nick_ptr = (char *)kvi_realloc(m_nick_ptr,len+1);
+ kvi_memmove((void *)m_nick_ptr,(void *)"*",len);
+ }
+ *(m_nick_ptr+len) = '\0'; //With zero length nick it will be just an empty-string
+ if(!(*p)){
+ setHost("*");
+ setUsername("*");
+ return p;
+ }
+ szMask = ++p;
+ //The username
+ while(*p && (*p != '@'))p++;
+ len = p - szMask;
+ if(len > 0){
+ m_user_ptr = (char *)kvi_realloc(m_user_ptr,len+1);
+ kvi_memmove((void *)m_user_ptr,(void *)szMask,len);
+ } else {
+ len = 1;
+ m_user_ptr = (char *)kvi_realloc(m_user_ptr,len+1);
+ kvi_memmove((void *)m_user_ptr,(void *)"*",len);
+ }
+ *(m_user_ptr+len) = '\0';
+ if(!(*p)){
+ setHost("*");
+ return p;
+ }
+ szMask = ++p;
+ //And finally the host
+ while(*p && (*p != c))p++;
+ len = p - szMask;
+ if(len > 0){
+ m_host_ptr = (char *)kvi_realloc(m_host_ptr,len+1);
+ kvi_memmove((void *)m_host_ptr,(void *)szMask,len);
+ } else {
+ len = 1;
+ m_host_ptr = (char *)kvi_realloc(m_host_ptr,len+1);
+ kvi_memmove((void *)m_host_ptr,(void *)"*",len);
+ }
+ *(m_host_ptr+len) = '\0';
+ return p;
+}
+
+const char * KviIrcMask::setUserhostMask(const char *szMask)
+{
+ __range_valid(szMask);
+ //nick[*]=<+!->username@host.top
+ //0123456789
+ register const char *p=szMask;
+ // Run over nick....
+ while(*p && (*p != '*') && (*p != '=') && (!isspace(*p)))p++;
+ // extract it
+ int len = p - szMask;
+ if(len > 0){
+ m_nick_ptr = (char *)kvi_realloc(m_nick_ptr,len+1);
+ kvi_memmove((void *)m_nick_ptr,(void *)szMask,len);
+ } else { //Empty nick...set it to "*"
+ len = 1;
+ m_nick_ptr = (char *)kvi_realloc(m_nick_ptr,len+1);
+ kvi_memmove((void *)m_nick_ptr,(void *)"*",len);
+ }
+ *(m_nick_ptr+len) = '\0'; //With zero length nick it will be just an empty-string
+ // now skip all the flags
+ while(*p && ((*p=='*')||(*p=='=')||(*p=='+')||(*p=='-')) && (!isspace(*p)))p++;
+ // check...
+ if((!(*p)) || isspace(*p)){
+ // ooops , finished or isspace
+ setHost("*");
+ setUsername("*");
+ while(*p && isspace(*p))p++;
+ return p;
+ }
+
+ szMask = p;
+ //The username
+ while(*p && (*p != '@') && (!isspace(*p)))p++;
+ len = p - szMask;
+ if(len > 0){
+ m_user_ptr = (char *)kvi_realloc(m_user_ptr,len+1);
+ kvi_memmove((void *)m_user_ptr,(void *)szMask,len);
+ } else {
+ len = 1;
+ m_user_ptr = (char *)kvi_realloc(m_user_ptr,len+1);
+ kvi_memmove((void *)m_user_ptr,(void *)"*",len);
+ }
+ *(m_user_ptr+len) = '\0';
+
+ if((!(*p))||isspace(*p)){
+ // oops finished or isspace
+ setHost("*");
+ while(*p && isspace(*p))p++;
+ return p;
+ }
+ szMask = ++p;
+ //And finally the host
+ while(*p && (!isspace(*p)))p++;
+ len = p - szMask;
+ if(len > 0){
+ m_host_ptr = (char *)kvi_realloc(m_host_ptr,len+1);
+ kvi_memmove((void *)m_host_ptr,(void *)szMask,len);
+ } else {
+ len = 1;
+ m_host_ptr = (char *)kvi_realloc(m_host_ptr,len+1);
+ kvi_memmove((void *)m_host_ptr,(void *)"*",len);
+ }
+ *(m_host_ptr+len) = '\0';
+ while(*p && isspace(*p))p++;
+ return p;
+}
+
+*/
+
+KviIrcMask::KviIrcMask()
+{
+ m_szHost = m_szWild;
+ m_szUser = m_szWild;
+ m_szNick = m_szWild;
+}
+
+KviIrcMask::KviIrcMask(const QString &szMask)
+{
+ static QString szWild("*");
+ const QChar * b = KviQString::nullTerminatedArray(szMask);
+ if(b)
+ {
+ const QChar * p = b;
+ while(p->unicode() && (p->unicode() != '!'))p++;
+ if(p->unicode())
+ {
+ if(p != b)
+ {
+ m_szNick.setUnicode(b,p-b);
+ } else {
+ m_szNick = szWild; // ???
+ }
+ } else {
+ if(p != b)m_szNick.setUnicode(b,p-b);
+ else m_szNick = szWild; // ???
+ m_szUser = szWild;
+ m_szHost = szWild;
+ return;
+ }
+ p++;
+ b = p;
+ while(p->unicode() && (p->unicode() != '@'))p++;
+ if(p->unicode())
+ {
+ if(p != b)
+ {
+ m_szUser.setUnicode(b,p-b);
+ } else {
+ m_szUser = szWild; // ???
+ }
+ } else {
+ if(p != b)m_szUser.setUnicode(b,p-b);
+ else m_szUser = szWild; // ???
+ m_szHost = szWild;
+ return;
+ }
+ p++;
+ b=p;
+ while(p->unicode())p++;
+ if(p != b)
+ {
+ m_szHost.setUnicode(b,p-b);
+ } else {
+ m_szHost = szWild; // ???
+ }
+
+ } else {
+ m_szUser = szWild;
+ m_szHost = szWild;
+ m_szNick = szWild;
+ }
+}
+
+QString KviIrcMask::m_szWild("*");
+
+bool KviIrcMask::hasNumericHost() const
+{
+ const QChar * p = KviQString::nullTerminatedArray(m_szHost);
+ if(!p)return false;
+ int nPoints = 0;
+ int nDoublePoints = 0;
+ unsigned short uc;
+ while((uc = p->unicode()))
+ {
+ if(uc == '.')nPoints++; // ipv6 masks can contain dots too!
+ else {
+ if(uc == ':')nDoublePoints++;
+ else {
+ if((uc < '0') || (uc > '9'))
+ {
+#ifdef COMPILE_USE_QT4
+ uc = p->toUpper().unicode();
+#else
+ uc = p->upper().unicode();
+#endif
+ if((uc < 'A') || (uc > 'F'))return false;
+ }
+ }
+ }
+ p++;
+ }
+ return ((nPoints == 3) || (nDoublePoints > 1));
+}
+
+
+/**
+* Retuns in szMask the specified (if possible) mask of this user.<br>
+* If the host or username are not known , the mask may contain less information
+* than requested.<br>
+* Mask types:<br>
+* 0 : nick!user@machine.host.top (nick!user@XXX.XXX.XXX.XXX) (default)<br>
+* 1 : nick!user@*.host.top (nick!user@XXX.XXX.XXX.*)<br>
+* 2 : nick!user@*<br>
+* 3 : nick!*@machine.host.top (nick!user@XXX.XXX.XXX.XXX)<br>
+* 4 : nick!*@*.host.top (nick!user@XXX.XXX.XXX.*)<br>
+* 5 : nick!*@*<br>
+* 6 : *!user@machine.host.top (*!user@XXX.XXX.XXX.XX)<br>
+* 7 : *!user@*.host.top (*!user@XXX.XXX.XXX.*)<br>
+* 8 : *!user@*<br>
+* 9 : *!*@machine.host.top (*!*@XXX.XXX.XXX.XXX)<br>
+* 10: *!*@*.host.top (*!*@XXX.XXX.XXX.*)<br>
+* 11: nick!*user@machine.host.top (nick!*user@machine.host.top)<br>
+* 12: nick!*user@*.host.top (nick!*user@*.host.top)<br>
+* 13: nick!*user@*<br>
+* 14: *!*user@machine.host.top (*!*user@machine.host.top)<br>
+* 15: *!*user@*.host.top (*!*user@*.host.top)<br>
+* 16: *!*user@*<br>
+* 17: nick!~user@*.host.top (nick!~user@XXX.XXX.*)
+* 18: nick!*@*.host.top (nick!*@XXX.XXX.*)
+* 19: *!~user@*.host.top (*!~user@XXX.XXX.*)
+* 20: nick!*user@*.host.top (nick!*user@XXX.XXX.*)
+* 21: *!*user@*.host.top (*!user@*XXX.XXX.*)
+* smart versions of the masks 17-21 that try take care of masked ip addresses
+* in the form xxx.xxx.INVALID-TOP-MASK
+* 22: nick!~user@*.host.top (nick!~user@XXX.XXX.*)
+* 23: nick!*@*.host.top (nick!*@XXX.XXX.*)
+* 24: *!~user@*.host.top (*!~user@XXX.XXX.*)
+* 25: nick!*user@*.host.top (nick!*user@XXX.XXX.*)
+* 26: *!*user@*.host.top (*!user@*XXX.XXX.*)
+* If some data is missing , these types may change:<br>
+* For example , if hostname is missing , the mask type 3 or 4 may be reduced to type 5
+*/
+
+/*
+** ident is fun.. ahem
+** prefixes used:
+** none I line with ident
+** ^ I line with OTHER type ident
+** ~ I line, no ident
+** + i line with ident
+** = i line with OTHER type ident
+** - i line, no ident
+*/
+
+static unsigned char maskTable[27][3] = {
+ { 0 , 0 , 0 }, //0 means normal block
+ { 0 , 0 , 2 }, //2 in the third field means type *.abc.host.top (or XXX.XXX.XXX.*) host mask
+ { 0 , 0 , 1 }, //2 in the second field means *user (strip prefixes)
+ { 0 , 1 , 0 }, //1 means *
+ { 0 , 1 , 2 }, //3 in the third field means type *.host.top (or XXX.XXX.*) host mask
+ { 0 , 1 , 1 }, //4 in the third field is like 3 but tries to detect masked ip addresses too
+ { 1 , 0 , 0 },
+ { 1 , 0 , 2 },
+ { 1 , 0 , 1 },
+ { 1 , 1 , 0 },
+ { 1 , 1 , 2 },
+ { 0 , 2 , 0 },
+ { 0 , 2 , 2 },
+ { 0 , 2 , 1 },
+ { 1 , 2 , 0 },
+ { 1 , 2 , 2 },
+ { 1 , 2 , 1 },
+ { 0 , 0 , 3 },
+ { 0 , 1 , 3 },
+ { 1 , 0 , 3 },
+ { 0 , 2 , 3 },
+ { 1 , 2 , 3 },
+ { 0 , 0 , 4 },
+ { 0 , 1 , 4 },
+ { 1 , 0 , 4 },
+ { 0 , 2 , 4 },
+ { 1 , 2 , 4 }
+};
+
+void KviIrcMask::mask(QString &szMask,MaskType eMaskType) const
+{
+ if((((int)eMaskType) > 26)||(((int)eMaskType) < 0))eMaskType = NickUserHost;
+ szMask = maskTable[((int)eMaskType)][0] ? m_szWild : m_szNick;
+ szMask.append("!");
+ switch(maskTable[((int)eMaskType)][1])
+ {
+ case 0:
+ szMask.append(m_szUser);
+ break;
+ case 1:
+ szMask.append(m_szWild);
+ break;
+ default:
+ if (m_szUser.length() > 0) {
+ if(m_szUser[0].unicode() != '*')
+ szMask.append(m_szWild);
+ if ((m_szUser[0].unicode() == '~') ||
+ (m_szUser[0].unicode() == '^') ||
+ (m_szUser[0].unicode() == '+') ||
+ (m_szUser[0].unicode() == '-') ||
+ (m_szUser[0].unicode() == '='))szMask.append(m_szUser.right(m_szUser.length() - 1));
+ else
+ szMask.append(m_szUser);
+ }
+ break;
+ }
+ szMask.append('@');
+ switch(maskTable[((int)eMaskType)][2])
+ {
+ case 0:
+ szMask.append(m_szHost);
+ break;
+ case 1:
+ szMask.append(m_szWild);
+ break;
+ case 2:
+ if(m_szHost != m_szWild)
+ {
+ if(hasNumericHost())
+ {
+ QString szHost(m_szHost.left(getIpDomainMaskLen()));
+ szMask.append(szHost);
+ szMask.append(m_szWild);
+ } else {
+ szMask.append(m_szWild);
+ szMask.append(getHostDomainMask());
+ }
+ } else {
+ szMask.append(m_szWild);
+ }
+ break;
+ case 3:
+ if(m_szHost != m_szWild)
+ {
+ if(hasNumericHost())
+ {
+ QString szHost(m_szHost.left(getLargeIpDomainMaskLen()));
+ szMask.append(szHost);
+ szMask.append(m_szWild);
+ } else {
+ szMask.append(m_szWild);
+ szMask.append(getLargeHostDomainMask());
+ }
+ } else {
+ szMask.append(m_szWild);
+ }
+ break;
+ default: // case 4 and others
+ if(m_szHost != m_szWild)
+ {
+ if(hasNumericHost() || hasMaskedIp())
+ {
+ QString szHost(m_szHost.left(getLargeIpDomainMaskLen()));
+ szMask.append(szHost);
+ szMask.append(m_szWild);
+ } else {
+ szMask.append(m_szWild);
+ szMask.append(getLargeHostDomainMask());
+ }
+ } else {
+ szMask.append(m_szWild);
+ }
+ break;
+ }
+}
+
+
+/*
+bool KviIrcMask::matches(const char *szMask)
+{
+ const char * ret1;
+ const char * ret2;
+
+ if(kvi_matchWildExprWithTerminator(szMask,m_nick_ptr,'!',&ret1,&ret2))
+ {
+ if(*ret1 == '!')
+ {
+ ret1++;
+ if(kvi_matchWildExprWithTerminator(ret1,m_user_ptr,'@',&ret1,&ret2))
+ {
+ if(*ret1 == '@')
+ {
+ ret1++;
+ return kvi_matchWildExpr(ret1,m_host_ptr);
+ }
+ }
+ }
+ }
+ return false;
+}
+*/
+
+/*
+bool KviIrcMask::matchesFixed(const char *szMask) const
+{
+ const char * ret1;
+ const char * ret2;
+
+ if(kvi_matchStringWithTerminator(m_nick_ptr,szMask,'!',&ret1,&ret2))
+ {
+ if(*ret2 == '!')
+ {
+ ret2++;
+ if(kvi_matchStringWithTerminator(m_user_ptr,ret2,'@',&ret1,&ret2))
+ {
+ if(*ret2 == '@')
+ {
+ ret2++;
+ return kvi_matchString(m_host_ptr,ret2);
+ }
+ }
+ }
+ }
+ return false;
+}
+*/
+
+/*
+bool KviIrcMask::matchedBy(const QString &szMask) const
+{
+ const char * ret1;
+ const char * ret2;
+
+ if(kvi_matchStringWithTerminator(szMask,m_nick_ptr,'!',&ret1,&ret2))
+ {
+ if(*ret1 == '!')
+ {
+ ret1++;
+ if(kvi_matchStringWithTerminator(ret1,m_user_ptr,'@',&ret1,&ret2))
+ {
+ if(*ret1 == '@')
+ {
+ ret1++;
+ return kvi_matchString(ret1,m_host_ptr);
+ }
+ }
+ }
+ }
+ return false;
+}
+*/
+
+bool KviIrcMask::matches(const KviIrcMask &mask) const
+{
+ if(KviQString::matchWildExpressionsCI(m_szNick,mask.m_szNick))
+ {
+ if(KviQString::matchWildExpressionsCI(m_szUser,mask.m_szUser))
+ {
+ if(KviQString::matchWildExpressionsCI(m_szHost,mask.m_szHost))return true;
+ }
+ }
+ return false;
+}
+
+bool KviIrcMask::matchesFixed(const KviIrcMask &mask) const
+{
+ if(KviQString::matchStringCI(m_szNick,mask.m_szNick,0,1))
+ {
+ if(KviQString::matchStringCI(m_szUser,mask.m_szUser,0,1))
+ {
+ if(KviQString::matchStringCI(m_szHost,mask.m_szHost,0,1))return true;
+ }
+ }
+ return false;
+}
+
+/*
+bool KviIrcMask::matches(const char * nick,const char * user,const char * host)
+{
+ if(nick)
+ {
+ if(!kvi_matchWildExpr(m_nick_ptr,nick))return false;
+ }
+
+ if(user)
+ {
+ if(!kvi_matchWildExpr(m_user_ptr,user))return false;
+ }
+
+ if(host)
+ {
+ if(!kvi_matchWildExpr(m_host_ptr,host))return false;
+ }
+ return true;
+}
+*/
+
+bool KviIrcMask::matchesFixed(const QString &nick,const QString &user,const QString &host) const
+{
+ if(!KviQString::matchStringCI(m_szNick,nick,0,1))return false;
+ if(!KviQString::matchStringCI(m_szUser,user,0,1))return false;
+ if(!KviQString::matchStringCI(m_szHost,host,0,1))return false;
+ return true;
+}
+
+//Internals for mask()
+
+int KviIrcMask::getIpDomainMaskLen() const
+{
+ int len = m_szHost.length();
+ const QChar *p = m_szHost.unicode();
+ const QChar *b = p;
+ p += len;
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.') && (p->unicode() != ':'))p--;
+ }
+ // 000.000.000.000
+ // p
+ //
+ return (p == b) ? 0 : ((p-b) + 1);
+}
+
+
+int KviIrcMask::getLargeIpDomainMaskLen() const
+{
+ int len = m_szHost.length();
+ const QChar *p = m_szHost.unicode();
+ const QChar *b = p;
+ p += len;
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.') && (p->unicode() != ':'))p--;
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.') && (p->unicode() != ':'))p--;
+ }
+ }
+ // 000.000.000.000
+ // p
+ //
+ return (p == b) ? 0 : ((p-b) + 1);
+}
+
+QString KviIrcMask::getHostDomainMask() const
+{
+ int len = m_szHost.length();
+ const QChar *p=KviQString::nullTerminatedArray(m_szHost);
+ if(!p)return QString::null;
+ const QChar *b = p;
+ while(p->unicode() && p->unicode() != '.')p++;
+ QString ret(p,len - (p - b));
+ return ret;
+}
+
+
+QString KviIrcMask::getLargeHostDomainMask() const
+{
+ int len = m_szHost.length();
+ const QChar *p = m_szHost.unicode();
+ const QChar *b = p;
+ p += len;
+
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.'))p--;
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.'))p--;
+ }
+ }
+
+ // xyz.klm.abc.host.top
+ // p
+
+ QString ret(p,len - (p - b));
+ return ret;
+}
+
+// this is just a GUESS and must be called AFTER making sure that it is NOT a plain numeric IP
+bool KviIrcMask::hasMaskedIp() const
+{
+ int len = m_szHost.length();
+ const QChar *p = m_szHost.unicode();
+ const QChar *b = p;
+ if(len == 0)return false;
+ //run to the end
+ p += len;
+ const QChar *e = p;
+ p--;
+ while((b < p) && (p->unicode() != '.'))p--;
+ return ((e - p) > 4); // at the moment 4 should be enough : the largest top part is "name"
+}
+
+
+bool KviIrcMask::operator==(const KviIrcMask &user)
+{
+ if(KviQString::equalCI(m_szNick,user.m_szNick))
+ {
+ if(KviQString::equalCI(m_szUser,user.m_szUser))
+ {
+ if(KviQString::equalCI(m_szHost,user.m_szHost))return true;
+ }
+ }
+ return false;
+}
+
+bool KviIrcMask::hasWildNick()
+{
+ const QChar * aux = KviQString::nullTerminatedArray(m_szNick);
+ if(!aux)return false;
+ unsigned short uc;
+ while((uc = aux->unicode()))
+ {
+ if((uc == '*') || (uc == '?'))return true;
+ aux++;
+ }
+ return false;
+}
+
+int KviIrcMask::nonWildChars()
+{
+ int iCnt = 0;
+ const QChar * aux = KviQString::nullTerminatedArray(m_szNick);
+ if(!aux)return 0;
+ unsigned short uc;
+
+ while((uc = aux->unicode()))
+ {
+ if((uc != '*') && (uc != '?'))iCnt++;
+ aux++;
+ }
+
+ aux = KviQString::nullTerminatedArray(m_szUser);
+ while((uc = aux->unicode()))
+ {
+ if((uc != '*') && (uc != '?'))iCnt++;
+ aux++;
+ }
+
+
+ aux = KviQString::nullTerminatedArray(m_szHost);
+ while((uc = aux->unicode()))
+ {
+ if((uc != '*') && (uc != '?'))iCnt++;
+ aux++;
+ }
+ return iCnt;
+}
diff --git a/src/kvilib/irc/kvi_ircmask.h b/src/kvilib/irc/kvi_ircmask.h
new file mode 100644
index 00000000..3c9ccf5d
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircmask.h
@@ -0,0 +1,164 @@
+#ifndef _KVI_IRCMASK_H_
+#define _KVI_IRCMASK_H_
+
+//=============================================================================
+//
+// File : kvi_ircmask.h
+// Creation date : Fri Jan 8 1999 19:50:35 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+// originally this file was named kvi_ircuser.h and the class was KviIrcUser
+// ported to UNICODE on 2004.10.28 1:50 am
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_qstring.h"
+
+//=============================================================================
+// Irc user mask abstraction
+//=============================================================================
+
+class KVILIB_API KviIrcMask : public KviHeapObject
+{
+ friend class KviIrcUserList;
+ friend class KviIrcUserChanList;
+private:
+ QString m_szNick;
+ QString m_szUser;
+ QString m_szHost;
+ static QString m_szWild;
+public:
+ // Sets the nick for this user.<br>
+ // If szNick is NULL or it points to an empty string the nick is set to "*".<br>
+ void setNick(const QString &szNick){ m_szNick = szNick.isEmpty() ? m_szWild : szNick; };
+ // Sets the username for this user.<br>
+ // If szUsername is NULL or it points to an empty string the username is set to "*".<br>
+ void setUsername(const QString &szUser){ m_szUser = szUser.isEmpty() ? m_szWild : szUser; };
+ void setUser(const QString &szUser){ m_szUser = szUser.isEmpty() ? m_szWild : szUser; };
+ // Sets the host for this user.<br>
+ // If szHost is NULL or it points to an empty string the host is set to "*".<br>
+ void setHost(const QString &szHost){ m_szHost = szHost.isEmpty() ? m_szWild : szHost; };
+ // Sets the host , nick and username extracting it from an irc mask:<br>
+ // nick!user@host<br>
+ // The mask is terminated by end-of string null character or a character equal to c in the string.<br>
+ // Returns the pointer to the end of the mask in the szMask string.(c or null-terminator)<br>
+ //const char * setMask(const QString &szMask,char c=' ');
+ // Sets the host , nick and username extracting it from an userhost mask:<br>
+ // nick[*]=<+|->user@host<br>
+ // The mask is terminated by end-of string null char or a space character.<br>
+ // Returns the pointer to the next non-space char in the szMask string or to the null-terminator<br>
+ // If there are no more masks avaiable.
+ // WARNING : the szMask pointer can NOT be NULL
+ //const char *setUserhostMask(const QString &szMask);
+ // Returns the nick of this user.<br>
+ // In the worst case you get a string == "*"<br>
+ const QString &nick() const { return m_szNick; };
+ // DEPRECATED!
+ const QString &username() const { return m_szUser; };
+ const QString &user() const { return m_szUser; };
+ const QString &host() const { return m_szHost; };
+
+ bool hasUser() const { return !(m_szUser.isEmpty() || (m_szUser == m_szWild)); };
+ bool hasHost() const { return !(m_szHost.isEmpty() || (m_szHost == m_szWild)); };
+
+ bool hasNumericHost() const;
+ // Retuns in szMask the specified (if possible) mask of this user.<br>
+ // If the host or username are not known , the mask may contain less information
+ // than requested.<br>
+
+ enum MaskType
+ {
+ NickUserHost = 0, // nick!~user@machine.host.top (nick!~user@XXX.XXX.XXX.XXX) (default)
+ NickUserNet = 1, // 1 : nick!~user@*.abc.host.top (nick!~user@XXX.XXX.XXX.*)
+ NickUser = 2, // 2 : nick!~user@*
+ NickHost = 3, // 3 : nick!*@machine.host.top (nick!*@XXX.XXX.XXX.XXX)
+ NickNet = 4, // 4 : nick!*@*.abc.host.top (nick!*@XXX.XXX.XXX.*)
+ Nick = 5, // 5 : nick!*@*
+ UserHost = 6, // 6 : *!~user@machine.host.top (*!~user@XXX.XXX.XXX.XXX)
+ UserNet = 7, // 7 : *!~user@*.abc.host.top (*!~user@XXX.XXX.XXX.*)
+ User = 8, // 8 : *!~user@*
+ Host = 9, // 9 : *!*@machine.host.top (*!*@XXX.XXX.XXX.XXX)
+ Net = 10, // 10: *!*@*.abc.host.top (*!*@XXX.XXX.XXX.*)
+ NickCleanUserHost = 11, // 11 : nick!*user@machine.host.top (nick!*user@XXX.XXX.XXX.XXX)
+ NickCleanUserNet = 12, // 12 : nick!*user@*.abc.host.top (nick!*user@XXX.XXX.XXX.*)
+ NickCleanUser = 13, // 13 : nick!*user@*
+ CleanUserHost = 14, // 14 : *!*user@machine.host.top (*!user@*XXX.XXX.XXX.XXX)
+ CleanUserNet = 15, // 15 : *!*user@*.abc.host.top (*!user@*XXX.XXX.XXX.*)
+ CleanUser = 16, // 16 : *!*user@*
+ NickUserLargeNet = 17, // 17 : nick!~user@*.host.top (nick!~user@XXX.XXX.*)
+ NickLargeNet = 18, // 18 : nick!*@*.host.top (nick!*@XXX.XXX.*)
+ UserLargeNet = 19, // 19 : *!~user@*.host.top (*!~user@XXX.XXX.*)
+ NickCleanUserLargeNet = 20, // 20 : nick!*user@*.host.top (nick!*user@XXX.XXX.*)
+ CleanUserLargeNet = 21, // 21 : *!*user@*.host.top (*!user@*XXX.XXX.*)
+ // smart versions of the masks 17-21 that try take care of masked ip addresses
+ // in the form xxx.xxx.INVALID-TOP-MASK
+ NickUserSmartNet = 22, // 22 : nick!~user@*.host.top (nick!~user@XXX.XXX.*)
+ NickSmartNet = 23, // 23 : nick!*@*.host.top (nick!*@XXX.XXX.*)
+ UserSmartNet = 24, // 24 : *!~user@*.host.top (*!~user@XXX.XXX.*)
+ NickCleanUserSmartNet = 25, // 25 : nick!*user@*.host.top (nick!*user@XXX.XXX.*)
+ CleanUserSmartNet = 26 // 26 : *!*user@*.host.top (*!user@*XXX.XXX.*)
+ };
+
+ void mask(QString &szMask,MaskType eMaskType = NickCleanUserHost) const;
+ bool hasWildNick();
+
+ // Wild external matches (this and external are wild)
+
+// bool matches(const char *szMask);
+// // passing 0 as one of params here means that it is a match by default
+// bool matches(const char *nick,const char *user,const char *host);
+ bool matches(const KviIrcMask &mask) const;
+
+
+ // Fixed external matches (this is wild , external is fixed)
+ bool matchesFixed(const QString &nick,const QString &user,const QString &host) const;
+// bool matchesFixed(const QString &szMask) const;
+ bool matchesFixed(const KviIrcMask &mask) const;
+
+ // Fixed internal matches (this is fixed , external is wild)
+ //bool matchedBy(const QString &szMask) const;
+ bool matchedBy(const KviIrcMask &mask) const { return mask.matchesFixed(*this); };
+
+ int nonWildChars();
+ bool operator==(const KviIrcMask &user);
+public:
+ // Constructs an empty mask (*!*@*)
+ KviIrcMask();
+ // Constructs this KviIrcMask object from a string mask
+ KviIrcMask(const QString &szMask);
+ // Carbon copy
+ KviIrcMask(const KviIrcMask &ircUser)
+ : m_szNick(ircUser.m_szNick), m_szUser(ircUser.m_szUser), m_szHost(ircUser.m_szHost) {};
+ KviIrcMask(const QString &nick,const QString &user,const QString &host)
+ : m_szNick(nick), m_szUser(user), m_szHost(host) {};
+private:
+ int getIpDomainMaskLen() const;
+ QString getHostDomainMask() const;
+ int getLargeIpDomainMaskLen() const;
+ QString getLargeHostDomainMask() const;
+ // this is just a GUESS and must be called AFTER making sure that it is NOT a plain numeric IP
+ bool hasMaskedIp() const;
+};
+
+
+
+
+#endif //_KVI_IRCMASK_H_
diff --git a/src/kvilib/irc/kvi_ircserver.cpp b/src/kvilib/irc/kvi_ircserver.cpp
new file mode 100644
index 00000000..5f03fb5e
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircserver.cpp
@@ -0,0 +1,373 @@
+//=============================================================================
+//
+// File : kvi_ircserver.cpp
+// Creation date : Mon Jul 10 2000 03:42:59 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_ircserver.h"
+#include "kvi_malloc.h"
+
+#include "kvi_config.h"
+#include "kvi_nickserv.h"
+#include "kvi_time.h"
+#include "kvi_proxydb.h"
+#include <stdlib.h>
+
+// This is not allowed on windows unless we force the symbol to be undefined
+// It works on linux since gcc allows undefined symbols by default
+// but it is also "theoretically" wrong:
+// kvilib is not linked to kvirc: it's kvirc being linked to kvilib
+// thus kvilib should not depend on symbols defined in the kvirc core.
+// We must find another way to do that (like having just the id and finding
+// the proxy in the kvirc core, or just passing the pointer to the db from outside).
+// Pragma
+
+//extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
+
+// FIXME: This should be renamed to KviServer or sth like that
+KviIrcServer::KviIrcServer()
+{
+ m_pReconnectInfo=0;
+ m_uFlags = 0;
+ m_uPort = 6667;
+ m_pChannelList = 0;
+ m_bAutoConnect = false;
+ m_iProxy = -1;
+}
+
+KviProxy* KviIrcServer::proxyServer(KviProxyDataBase * pDb)
+{
+ int i=0;
+ if(proxy()<0) return 0;
+ KviPointerList<KviProxy> * proxylist = pDb->proxyList();
+ for(KviProxy * p = proxylist->first();p;p = proxylist->next())
+ {
+ if(i==proxy()) return p;
+ i++;
+ }
+ return 0;
+}
+
+KviIrcServer::KviIrcServer(const KviIrcServer &serv)
+{
+ m_pReconnectInfo = 0;
+ m_szHostname = serv.m_szHostname;
+ m_szIp = serv.m_szIp;
+ m_szDescription = serv.m_szDescription;
+ m_szUser = serv.m_szUser;
+ m_szPass = serv.m_szPass;
+ m_uPort = serv.m_uPort;
+ m_szNick = serv.m_szNick;
+ m_szRealName = serv.m_szRealName;
+ m_szEncoding = serv.m_szEncoding;
+ m_uFlags = serv.m_uFlags;
+ m_szInitUMode = serv.m_szInitUMode;
+ m_szOnConnectCommand = serv.m_szOnConnectCommand;
+ m_szOnLoginCommand = serv.m_szOnLoginCommand;
+ m_szLinkFilter = serv.m_szLinkFilter;
+ m_szId = serv.m_szId;
+ m_iProxy = serv.m_iProxy;
+ m_szUserIdentityId = serv.m_szUserIdentityId;
+ if(serv.m_pChannelList)
+ m_pChannelList = new QStringList(*(serv.m_pChannelList));
+ else m_pChannelList = 0;
+ m_bAutoConnect = serv.m_bAutoConnect;
+}
+
+void KviIrcServer::operator=(const KviIrcServer &serv)
+{
+ m_szHostname = serv.m_szHostname;
+ m_szIp = serv.m_szIp;
+ m_szDescription = serv.m_szDescription;
+ m_szUser = serv.m_szUser;
+ m_szPass = serv.m_szPass;
+ m_uPort = serv.m_uPort;
+ m_szNick = serv.m_szNick;
+ m_szRealName = serv.m_szRealName;
+ m_szEncoding = serv.m_szEncoding;
+ m_uFlags = serv.m_uFlags;
+ m_szInitUMode = serv.m_szInitUMode;
+ m_szOnConnectCommand = serv.m_szOnConnectCommand;
+ m_szOnLoginCommand = serv.m_szOnLoginCommand;
+ m_szLinkFilter = serv.m_szLinkFilter;
+ m_szId = serv.m_szId;
+ m_szUserIdentityId = serv.m_szUserIdentityId;
+ m_iProxy = serv.m_iProxy;
+ if(m_pChannelList)delete m_pChannelList;
+ if(serv.m_pChannelList)
+ m_pChannelList = new QStringList(*(serv.m_pChannelList));
+ else m_pChannelList = 0;
+ m_bAutoConnect = serv.m_bAutoConnect;
+}
+
+
+KviIrcServer::~KviIrcServer()
+{
+ if(m_pChannelList)delete m_pChannelList;
+ if(m_pReconnectInfo) delete m_pReconnectInfo;
+}
+
+void KviIrcServer::generateUniqueId()
+{
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+ KviQString::sprintf(m_szId,"myserver%d%d%d",tv.tv_usec,rand() % 1000,rand() % 1000);
+}
+
+QString KviIrcServer::ircUri()
+{
+ QString uri("irc");
+ if(useSSL())uri += "s";
+ if(isIpV6())uri += "6";
+ uri += "://";
+ uri += m_szHostname;
+
+ if(m_uPort!=6667)
+ {
+ uri += ":";
+ QString num;
+ num.setNum(m_uPort);
+ uri += num;
+ }
+ return uri;
+}
+
+void KviIrcServer::setAutoJoinChannelList(QStringList * pNewChannelList)
+{
+ if(m_pChannelList)delete m_pChannelList;
+ m_pChannelList = pNewChannelList;
+}
+
+
+bool KviIrcServer::load(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QHostname",&prefix);
+ m_szHostname = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QIp",&prefix);
+ m_szIp = cfg->readQStringEntry(tmp);
+ if(m_szHostname.isEmpty() && m_szIp.isEmpty())return false;
+ KviQString::sprintf(tmp,"%QDescription",&prefix);
+ m_szDescription = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QUser",&prefix);
+ m_szUser = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QPass",&prefix);
+ m_szPass = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QNick",&prefix);
+ m_szNick = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QRealName",&prefix);
+ m_szRealName = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QInitUmode",&prefix);
+ m_szInitUMode = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QAutoJoinChannels",&prefix);
+ QStringList l = cfg->readStringListEntry(tmp,QStringList());
+ if(l.count() > 0)setAutoJoinChannelList(new QStringList(l));
+ KviQString::sprintf(tmp,"%QAutoConnect",&prefix);
+ m_bAutoConnect = cfg->readBoolEntry(tmp,false);
+ KviQString::sprintf(tmp,"%QEncoding",&prefix);
+ m_szEncoding = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QOnConnectCommand",&prefix);
+ m_szOnConnectCommand = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QOnLoginCommand",&prefix);
+ m_szOnLoginCommand = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QLinkFilter",&prefix);
+ m_szLinkFilter = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QPort",&prefix);
+ m_uPort = cfg->readUIntEntry(tmp,6667);
+ KviQString::sprintf(tmp,"%QId",&prefix);
+ m_szId = cfg->readQStringEntry(tmp);
+ if(m_szId.isEmpty())generateUniqueId();
+ KviQString::sprintf(tmp,"%QIpV6",&prefix);
+ setIpV6(cfg->readBoolEntry(tmp,false));
+ KviQString::sprintf(tmp,"%QCacheIp",&prefix);
+ setCacheIp(cfg->readBoolEntry(tmp,false)); // true ?
+ KviQString::sprintf(tmp,"%QSSL",&prefix);
+ setUseSSL(cfg->readBoolEntry(tmp,false));
+ KviQString::sprintf(tmp,"%QProxy",&prefix);
+ setProxy(cfg->readIntEntry(tmp,-2));
+ KviQString::sprintf(tmp,"%QUserIdentityId",&prefix);
+ m_szUserIdentityId = cfg->readQStringEntry(tmp);
+ return true;
+}
+
+void KviIrcServer::save(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QHostname",&prefix);
+ cfg->writeEntry(tmp,m_szHostname);
+ KviQString::sprintf(tmp,"%QId",&prefix);
+ cfg->writeEntry(tmp,m_szId);
+ if(!m_szIp.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QIp",&prefix);
+ cfg->writeEntry(tmp,m_szIp);
+ }
+ if(!m_szDescription.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QDescription",&prefix);
+ cfg->writeEntry(tmp,m_szDescription);
+ }
+ if(!m_szUser.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QUser",&prefix);
+ cfg->writeEntry(tmp,m_szUser);
+ }
+ if(!m_szPass.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QPass",&prefix);
+ cfg->writeEntry(tmp,m_szPass);
+ }
+ if(!m_szNick.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QNick",&prefix);
+ cfg->writeEntry(tmp,m_szNick);
+ }
+ if(!m_szRealName.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QRealName",&prefix);
+ cfg->writeEntry(tmp,m_szRealName);
+ }
+ if(!m_szInitUMode.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QInitUMode",&prefix);
+ cfg->writeEntry(tmp,m_szInitUMode);
+ }
+ if(autoJoinChannelList())
+ {
+ KviQString::sprintf(tmp,"%QAutoJoinChannels",&prefix);
+ cfg->writeEntry(tmp,*(autoJoinChannelList()));
+ }
+ if(autoConnect()) // otherwise it defaults to false anyway
+ {
+ KviQString::sprintf(tmp,"%QAutoConnect",&prefix);
+ cfg->writeEntry(tmp,autoConnect());
+ }
+ if(!m_szEncoding.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QEncoding",&prefix);
+ cfg->writeEntry(tmp,m_szEncoding);
+ }
+ if(!m_szOnConnectCommand.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QOnConnectCommand",&prefix);
+ cfg->writeEntry(tmp,m_szOnConnectCommand);
+ }
+ if(!m_szOnLoginCommand.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QOnLoginCommand",&prefix);
+ cfg->writeEntry(tmp,m_szOnLoginCommand);
+ }
+ if(!m_szLinkFilter.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QLinkFilter",&prefix);
+ cfg->writeEntry(tmp,m_szLinkFilter);
+ }
+ if(m_uPort != 6667)
+ {
+ KviQString::sprintf(tmp,"%QPort",&prefix);
+ cfg->writeEntry(tmp,m_uPort);
+ }
+ if(isIpV6())
+ {
+ KviQString::sprintf(tmp,"%QIpV6",&prefix);
+ cfg->writeEntry(tmp,isIpV6());
+ }
+ if(cacheIp())
+ {
+ KviQString::sprintf(tmp,"%QCacheIp",&prefix);
+ cfg->writeEntry(tmp,cacheIp());
+ }
+ if(useSSL())
+ {
+ KviQString::sprintf(tmp,"%QSSL",&prefix);
+ cfg->writeEntry(tmp,useSSL());
+ }
+ if(proxy()!=-2)
+ {
+ KviQString::sprintf(tmp,"%QProxy",&prefix);
+ cfg->writeEntry(tmp,proxy());
+ }
+ if(!m_szUserIdentityId.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QUserIdentityId",&prefix);
+ cfg->writeEntry(tmp,m_szUserIdentityId);
+ }
+}
+
+
+
+KviIrcNetwork::KviIrcNetwork(const KviIrcNetwork &src)
+{
+ m_pChannelList = 0;
+ m_pNickServRuleSet = 0;
+ copyFrom(src);
+}
+
+KviIrcNetwork::KviIrcNetwork(const QString &name)
+{
+ m_szName = name;
+ m_pChannelList = 0;
+ m_pNickServRuleSet = 0;
+ m_bAutoConnect = false;
+ // m_szEncoding = QString::null; // set by default
+}
+
+KviIrcNetwork::~KviIrcNetwork()
+{
+ if(m_pChannelList)delete m_pChannelList;
+ if(m_pNickServRuleSet)delete m_pNickServRuleSet;
+}
+
+void KviIrcNetwork::setAutoJoinChannelList(QStringList * pNewChannelList)
+{
+ if(m_pChannelList)delete m_pChannelList;
+ m_pChannelList = pNewChannelList;
+}
+
+void KviIrcNetwork::setNickServRuleSet(KviNickServRuleSet * s)
+{
+ if(m_pNickServRuleSet)delete m_pNickServRuleSet;
+ m_pNickServRuleSet = s;
+}
+
+
+void KviIrcNetwork::copyFrom(const KviIrcNetwork &src)
+{
+ m_szName = src.m_szName;
+ m_szEncoding = src.m_szEncoding;
+ m_szDescription = src.m_szDescription;
+ m_szNickName = src.m_szNickName;
+ m_szRealName = src.m_szRealName;
+ m_szUserName = src.m_szUserName;
+ m_bAutoConnect = src.m_bAutoConnect;
+ m_szUserIdentityId = src.m_szUserIdentityId;
+ m_szOnConnectCommand = src.m_szOnConnectCommand;
+ m_szOnLoginCommand = src.m_szOnLoginCommand;
+ if(m_pChannelList)delete m_pChannelList;
+ if(src.m_pChannelList)m_pChannelList = new QStringList(*(src.m_pChannelList));
+ else m_pChannelList = 0;
+ if(m_pNickServRuleSet)delete m_pNickServRuleSet;
+ if(src.m_pNickServRuleSet)m_pNickServRuleSet = new KviNickServRuleSet(*(src.m_pNickServRuleSet));
+ else m_pNickServRuleSet = 0;
+}
+
diff --git a/src/kvilib/irc/kvi_ircserver.h b/src/kvilib/irc/kvi_ircserver.h
new file mode 100644
index 00000000..4c0ca54d
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircserver.h
@@ -0,0 +1,206 @@
+#ifndef _KVI_IRCSERVER_H_
+#define _KVI_IRCSERVER_H_
+
+//=============================================================================
+//
+// File : kvi_ircserver.h
+// Creation date : Mon Jul 10 2000 03:24:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+#include <qstringlist.h>
+
+class KviConfig;
+class KviNickServRuleSet;
+class KviProxy;
+class KviProxyDataBase;
+class KviIrcServer;
+
+#define KVI_IRCSERVER_FLAG_IPV6 1
+#define KVI_IRCSERVER_FLAG_CACHEIP 2
+#define KVI_IRCSERVER_FLAG_SSL 4
+
+class KVILIB_API KviIrcServerReconnectInfo {
+public:
+ QString m_szNick;
+ QString m_szAwayReason;
+ QString m_szJoinChannels;
+ QStringList m_szOpenQueryes;
+ bool m_bIsAway;
+};
+
+class KVILIB_API KviIrcServer : public KviHeapObject
+{
+public:
+ KviIrcServer();
+ KviIrcServer(const KviIrcServer &serv);
+ ~KviIrcServer();
+public:
+ KviIrcServerReconnectInfo *m_pReconnectInfo;
+ QString m_szHostname; // the server hostname (or ip eventually)
+ QString m_szIp; // the server's cached ip (if we're caching)
+ QString m_szDescription; // the server description
+ kvi_u32_t m_uPort; // the server's port
+ unsigned short int m_uFlags; // flags
+
+ // Extended data
+ QString m_szUserIdentityId; // The user identity to use for this server: if empty
+ // Then use the network identity instead
+
+ QString m_szUser; // special username
+ QString m_szPass; // special password
+ QString m_szNick; // special nickname
+ QString m_szRealName; // special real name
+ QString m_szInitUMode; // special user mode
+ QString m_szOnConnectCommand; // the command to run on connect
+ QString m_szOnLoginCommand; // the command to run after login
+ QString m_szLinkFilter; // the link filter object
+ QString m_szEncoding; // if empty, use network encoding
+ QStringList * m_pChannelList; // Channels to auto join
+ bool m_bAutoConnect; // autoconnect
+ QString m_szId; // the server's may-be-unique id, may be auto-generated
+ int m_iProxy; // proxy server's id
+public:
+ int proxy() { return m_iProxy; };
+ KviProxy* proxyServer(KviProxyDataBase * pDb);
+
+ kvi_u32_t port() const { return m_uPort; };
+ const QString & ipAddress() const { return m_szIp; };
+ const QString & password() const { return m_szPass; };
+ const QString & nickName() const { return m_szNick; };
+ const QString & initUMode() const { return m_szInitUMode; };
+ const QString & hostName() const { return m_szHostname; };
+ const QString & ip() const { return m_szIp; };
+ const QString & onLoginCommand() const { return m_szOnLoginCommand; };
+ const QString & onConnectCommand() const { return m_szOnConnectCommand; };
+ const QString & userName() const { return m_szUser; };
+ const QString & realName() const { return m_szRealName; };
+ const QString & linkFilter() const { return m_szLinkFilter; };
+ const QString & description() const { return m_szDescription; };
+ const QString & encoding() const { return m_szEncoding; };
+ const QString & id() const { return m_szId; };
+ const QString & userIdentityId() const { return m_szUserIdentityId; };
+ bool autoConnect() const { return m_bAutoConnect; };
+ QStringList* autoJoinChannelList(){ return m_pChannelList; };
+ bool isIpV6() const { return (m_uFlags & KVI_IRCSERVER_FLAG_IPV6); };
+ bool useSSL() const { return (m_uFlags & KVI_IRCSERVER_FLAG_SSL); };
+ bool cacheIp() const { return (m_uFlags & KVI_IRCSERVER_FLAG_CACHEIP); };
+
+ void setProxy(int p){ m_iProxy = p; };
+ void setIpAddress(const QString &a){ m_szIp = a; };
+ void setPort(kvi_u32_t p){ m_uPort = p; };
+ void setHostName(const QString &n){ m_szHostname = n; };
+ void setDescription(const QString &d){ m_szDescription = d; };
+ void setUserName(const QString &u){ m_szUser = u; };
+ void setPassword(const QString &p){ m_szPass = p; };
+ void setNickName(const QString &n){ m_szNick = n; };
+ void setRealName(const QString &r){ m_szRealName = r; };
+ void setEncoding(const QString &e){ m_szEncoding = e; };
+ void setInitUMode(const QString &u){ m_szInitUMode = u; };
+ void setOnConnectCommand(const QString &cmd){ m_szOnConnectCommand = cmd; };
+ void setOnLoginCommand(const QString &cmd){ m_szOnLoginCommand = cmd; };
+ void setLinkFilter(const QString &f){ m_szLinkFilter = f; };
+ // the channel list must be allocated with new!
+ void setAutoJoinChannelList(QStringList * pNewChannelList);
+ void setAutoConnect(bool autoconnect) { m_bAutoConnect = autoconnect; };
+ void setUserIdentityId(const QString &szUserIdentityId){ m_szUserIdentityId = szUserIdentityId; };
+ void setIpV6(bool bSet)
+ {
+ if(bSet)m_uFlags |= KVI_IRCSERVER_FLAG_IPV6;
+ else m_uFlags &= ((unsigned short)~KVI_IRCSERVER_FLAG_IPV6);
+ };
+ void setUseSSL(bool bSet)
+ {
+ if(bSet)m_uFlags |= KVI_IRCSERVER_FLAG_SSL;
+ else m_uFlags &= ((unsigned short)~KVI_IRCSERVER_FLAG_SSL);
+ };
+ void setCacheIp(bool bSet)
+ {
+ if(bSet)m_uFlags |= KVI_IRCSERVER_FLAG_CACHEIP;
+ else m_uFlags &= ((unsigned short)~KVI_IRCSERVER_FLAG_CACHEIP);
+ };
+ void operator =(const KviIrcServer &s);
+
+ bool load(KviConfig * cfg,const QString &prefix);
+ void save(KviConfig * cfg,const QString &prefix);
+
+ void generateUniqueId();
+ void setId(const QString &szId){ m_szId = szId; if(m_szId.isEmpty())generateUniqueId(); };
+
+ QString ircUri();
+};
+
+class KVILIB_API KviIrcNetwork : public KviHeapObject
+{
+ friend class KviIrcServerDataBase;
+public:
+ KviIrcNetwork(const KviIrcNetwork &src);
+ KviIrcNetwork(const QString &name);
+ ~KviIrcNetwork();
+protected:
+ QString m_szName;
+ QString m_szDescription;
+ QString m_szEncoding; // if empty, use system default
+ QString m_szNickName; // preferred nick name
+ QString m_szUserName; // preferred user name
+ QString m_szRealName; // preferred real name
+ QString m_szOnConnectCommand; // the command to run on connect
+ QString m_szOnLoginCommand; // the command to run after login
+ QStringList * m_pChannelList; // Channels to auto join
+ KviNickServRuleSet * m_pNickServRuleSet; // set of nick serv rules
+ bool m_bAutoConnect; // autoconnect
+ QString m_szUserIdentityId; // The user identity to use for this server: if empty
+ // Then use the global primary identity
+public:
+ const QString & name() const { return m_szName; };
+ const QString & encoding() const { return m_szEncoding; };
+ const QString & description() const { return m_szDescription; };
+ const QString & nickName() const { return m_szNickName; };
+ const QString & realName() const { return m_szRealName; };
+ const QString & userName() const { return m_szUserName; };
+ const QString & onLoginCommand() const { return m_szOnLoginCommand; };
+ const QString & onConnectCommand() const { return m_szOnConnectCommand; };
+ const QString & userIdentityId() const { return m_szUserIdentityId; };
+ bool autoConnect() const { return m_bAutoConnect; };
+ QStringList* autoJoinChannelList(){ return m_pChannelList; };
+ KviNickServRuleSet * nickServRuleSet(){ return m_pNickServRuleSet; };
+ void setNickServRuleSet(KviNickServRuleSet * s);
+ void copyFrom(const KviIrcNetwork &d);
+ void setName(const QString &szName){ m_szName = szName; };
+ void setEncoding(const QString &szEncoding){ m_szEncoding = szEncoding; };
+ void setDescription(const QString &szDescription){ m_szDescription = szDescription; };
+ void setOnConnectCommand(const QString &cmd){ m_szOnConnectCommand = cmd; };
+ void setOnLoginCommand(const QString &cmd){ m_szOnLoginCommand = cmd; };
+ void setNickName(const QString &n){ m_szNickName = n; };
+ void setRealName(const QString &r){ m_szRealName = r; };
+ void setUserName(const QString &u){ m_szUserName = u; };
+ void setAutoJoinChannelList(QStringList * pNewChannelList);
+ void setAutoConnect(bool bAutoConnect){ m_bAutoConnect = bAutoConnect; };
+ void setUserIdentityId(const QString &szUserIdentityId){ m_szUserIdentityId = szUserIdentityId; };
+};
+
+
+
+#endif //_KVI_IRCSERVER_H_
diff --git a/src/kvilib/irc/kvi_ircserverdb.cpp b/src/kvilib/irc/kvi_ircserverdb.cpp
new file mode 100644
index 00000000..88198b12
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircserverdb.cpp
@@ -0,0 +1,646 @@
+//=============================================================================
+//
+// File : kvi_ircserverdb.cpp
+// Creation date : Mon Jul 10 2000 14:25:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qmessagebox.h>
+#include <qcheckbox.h>
+
+#include "kvi_ircserverdb.h"
+#include "kvi_config.h"
+#include "kvi_locale.h"
+#include "kvi_netutils.h"
+#include "kvi_nickserv.h"
+
+KviIrcServerDataBaseRecord::KviIrcServerDataBaseRecord(KviIrcNetwork * n)
+{
+ m_pNetwork = n;
+ m_pServerList = new KviPointerList<KviIrcServer>;
+ m_pServerList->setAutoDelete(true);
+ m_pCurrentServer = 0;
+}
+
+KviIrcServerDataBaseRecord::~KviIrcServerDataBaseRecord()
+{
+ delete m_pNetwork;
+ delete m_pServerList;
+}
+
+void KviIrcServerDataBaseRecord::insertServer(KviIrcServer *srv)
+{
+ m_pServerList->append(srv);
+}
+
+KviIrcServer * KviIrcServerDataBaseRecord::findServer(const KviIrcServer * pServer)
+{
+ for(KviIrcServer *s=m_pServerList->first();s;s=m_pServerList->next())
+ {
+ if(KviQString::equalCI(s->m_szHostname,pServer->m_szHostname) &&
+ (s->m_uPort == pServer->m_uPort) &&
+ (s->useSSL() == pServer->useSSL()) &&
+ (s->isIpV6() == pServer->isIpV6()))return s;
+ }
+ return 0;
+}
+
+void KviIrcServerDataBaseRecord::setCurrentServer(KviIrcServer *srv)
+{
+ if(m_pServerList->findRef(srv) != -1)m_pCurrentServer = srv;
+}
+
+KviIrcServer * KviIrcServerDataBaseRecord::currentServer()
+{
+ if(m_pCurrentServer)return m_pCurrentServer;
+ m_pCurrentServer = m_pServerList->first();
+ return m_pCurrentServer;
+}
+
+
+
+
+
+
+
+
+
+
+KviIrcServerDataBase::KviIrcServerDataBase()
+{
+ m_pRecords = new KviPointerHashTable<QString,KviIrcServerDataBaseRecord>(17,false);
+ m_pRecords->setAutoDelete(true);
+ m_pAutoConnectOnStartupServers = 0;
+ m_pAutoConnectOnStartupNetworks = 0;
+}
+
+KviIrcServerDataBase::~KviIrcServerDataBase()
+{
+ delete m_pRecords;
+ if(m_pAutoConnectOnStartupServers)delete m_pAutoConnectOnStartupServers;
+ if(m_pAutoConnectOnStartupNetworks)delete m_pAutoConnectOnStartupNetworks;
+}
+
+void KviIrcServerDataBase::clearAutoConnectOnStartupServers()
+{
+ if(!m_pAutoConnectOnStartupServers)return;
+ delete m_pAutoConnectOnStartupServers;
+ m_pAutoConnectOnStartupServers = 0;
+}
+
+void KviIrcServerDataBase::clearAutoConnectOnStartupNetworks()
+{
+ if(!m_pAutoConnectOnStartupNetworks)return;
+ delete m_pAutoConnectOnStartupNetworks;
+ m_pAutoConnectOnStartupNetworks = 0;
+}
+
+void KviIrcServerDataBase::clear()
+{
+ m_pRecords->clear();
+ m_szCurrentNetwork = "";
+}
+
+KviIrcServerDataBaseRecord * KviIrcServerDataBase::insertNetwork(KviIrcNetwork *n)
+{
+ KviIrcServerDataBaseRecord * r = new KviIrcServerDataBaseRecord(n);
+ m_pRecords->replace(n->name(),r);
+ return r;
+}
+
+KviIrcServerDataBaseRecord * KviIrcServerDataBase::findRecord(const QString &szNetName)
+{
+ return m_pRecords->find(szNetName);
+}
+
+
+KviIrcNetwork * KviIrcServerDataBase::findNetwork(const QString &szName)
+{
+ KviIrcServerDataBaseRecord * r = m_pRecords->find(szName);
+ if(!r)return 0;
+ return r->network();
+}
+
+KviIrcServerDataBaseRecord * KviIrcServerDataBase::currentRecord()
+{
+ KviIrcServerDataBaseRecord * r = 0;
+ if(!m_szCurrentNetwork.isEmpty())r = m_pRecords->find(m_szCurrentNetwork);
+ if(r)return r;
+
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*m_pRecords);
+ r = it.current();
+ if(!r)return 0;
+ m_szCurrentNetwork = r->network()->name();
+ return r;
+}
+
+void KviIrcServerDataBase::updateServerIp(KviIrcServer * pServer,const QString & ip)
+{
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*m_pRecords);
+ while(KviIrcServerDataBaseRecord * r = it.current())
+ {
+ KviIrcServer * srv = r->findServer(pServer);
+ if(srv)
+ {
+ srv->m_szIp = ip;
+ return;
+ }
+ ++it;
+ }
+}
+
+bool KviIrcServerDataBase::makeCurrentBestServerInNetwork(const QString &szNetName,KviIrcServerDataBaseRecord * r,QString &szError)
+{
+ m_szCurrentNetwork = szNetName;
+ // find a round-robin server in that network
+
+ if(r->m_pServerList->isEmpty())
+ {
+ szError = __tr2qs("The specified network has no server entries");
+ return false;
+ }
+
+ for(KviIrcServer * s = r->m_pServerList->first();s;s = r->m_pServerList->next())
+ {
+#ifdef COMPILE_USE_QT4
+ if(s->m_szDescription.contains("random",Qt::CaseInsensitive) ||
+ (s->m_szDescription.contains("round",Qt::CaseInsensitive) && s->m_szDescription.contains("robin",Qt::CaseInsensitive)))
+#else
+ if(s->m_szDescription.contains("random",false) ||
+ (s->m_szDescription.contains("round",false) && s->m_szDescription.contains("robin",false)))
+#endif
+ {
+ r->setCurrentServer(s);
+ return true;
+ }
+ }
+
+ // no explicit round robin... try some common names
+
+ QString tryAlso1,tryAlso2,tryAlso3;
+
+ KviQString::sprintf(tryAlso1,"irc.%Q.org",&szNetName);
+ KviQString::sprintf(tryAlso2,"irc.%Q.net",&szNetName);
+ KviQString::sprintf(tryAlso3,"irc.%Q.com",&szNetName);
+
+ for(KviIrcServer * ss = r->m_pServerList->first();ss;ss = r->m_pServerList->next())
+ {
+ if(KviQString::equalCI(ss->m_szHostname,tryAlso1) ||
+ KviQString::equalCI(ss->m_szHostname,tryAlso2) ||
+ KviQString::equalCI(ss->m_szHostname,tryAlso3))
+ {
+ r->setCurrentServer(ss);
+ return true;
+ }
+ }
+
+ // a random one in this network
+ return true;
+}
+
+
+bool KviIrcServerDataBase::makeCurrentServer(KviIrcServerDefinition * d,QString &szError)
+{
+ KviIrcServer * pServer = 0;
+
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*m_pRecords);
+ KviIrcServerDataBaseRecord * r = 0;
+ KviIrcServer * srv;
+
+ if(KviQString::equalCIN(d->szServer,"net:",4))
+ {
+ // net:networkname form
+ QString szNet = d->szServer;
+ szNet.remove(0,4);
+ KviIrcServerDataBaseRecord * r = m_pRecords->find(szNet);
+ if(r)return makeCurrentBestServerInNetwork(szNet,r,szError);
+ szError = __tr2qs("The server specification seems to be in the net:<string> but the network couln't be found in the database");
+ return false;
+ }
+
+ if(KviQString::equalCIN(d->szServer,"id:",3))
+ {
+ // id:serverid form
+ QString szId = d->szServer;
+ szId.remove(0,3);
+
+ while((r = it.current()))
+ {
+ for(srv = r->serverList()->first();srv && (!pServer);srv = r->serverList()->next())
+ {
+ if(KviQString::equalCI(srv->id(),szId))
+ {
+ pServer = srv;
+ goto search_finished;
+ }
+ }
+ ++it;
+ }
+ szError = __tr2qs("The server specification seems to be in the id:<string> form but the identifier coulnd't be found in the database");
+ return false;
+ }
+
+ it.toFirst();
+
+ while((r = it.current()))
+ {
+ for(srv = r->serverList()->first();srv && (!pServer);srv = r->serverList()->next())
+ {
+ if(KviQString::equalCI(srv->hostName(),d->szServer))
+ {
+ if(d->bIpV6 == srv->isIpV6())
+ {
+ if(d->bSSL == srv->useSSL())
+ {
+ if(d->bPortIsValid)
+ {
+ // must match the port
+ if(d->uPort == srv->port())
+ {
+ // port matches
+ if(!d->szLinkFilter.isEmpty())
+ {
+ // must match the link filter
+ if(KviQString::equalCI(d->szLinkFilter,srv->linkFilter()))
+ {
+ // link filter matches
+ pServer = srv;
+ goto search_finished;
+ } // else link filter doesn't match
+ } else {
+ // no need to match the link filter
+ pServer = srv;
+ goto search_finished;
+ }
+ } // else port doesn't match
+ } else {
+ // no need to match the port
+ if(!d->szLinkFilter.isEmpty())
+ {
+ // must match the link filter
+ if(KviQString::equalCI(d->szLinkFilter,srv->linkFilter()))
+ {
+ // link filter matches
+ pServer = srv;
+ goto search_finished;
+ } // else link filter doesn't match
+ } else {
+ // no need to match the link filter
+ pServer = srv;
+ goto search_finished;
+ }
+ }
+ }
+ }
+ }
+ }
+ ++it;
+ }
+
+search_finished:
+
+ if(r && pServer)
+ {
+ if(!d->szNick.isEmpty())pServer->m_szNick = d->szNick;
+ if(!d->szPass.isEmpty())pServer->m_szPass = d->szPass; // don't clear the pass!
+ if(!d->szInitUMode.isEmpty())pServer->m_szInitUMode = d->szInitUMode;
+
+ m_szCurrentNetwork = r->network()->name();
+ r->setCurrentServer(pServer);
+ return true;
+ }
+
+ // no such server: is it a valid ip address or hostname ?
+ bool bIsValidIpV4 = KviNetUtils::isValidStringIp(d->szServer);
+#ifdef COMPILE_IPV6_SUPPORT
+ bool bIsValidIpV6 =KviNetUtils::isValidStringIp_V6(d->szServer);
+#else
+ bool bIsValidIpV6 = false;
+#endif
+
+ if(!(bIsValidIpV4 || bIsValidIpV6))
+ {
+ // is it a valid hostname ? (must contain at least one dot)
+#ifdef COMPILE_USE_QT4
+ if(!d->szServer.contains('.'))
+#else
+ if(d->szServer.contains('.') < 1)
+#endif
+ {
+ // assume it is a network name!
+ KviIrcServerDataBaseRecord * r = m_pRecords->find(d->szServer);
+ if(r)return makeCurrentBestServerInNetwork(d->szServer,r,szError);
+ // else probably not a network name
+ }
+ }
+
+ // a valid hostname or ip address , not found in list : add it and make it current
+
+ r = m_pRecords->find(__tr2qs("Standalone Servers"));
+ if(!r)
+ {
+ r = new KviIrcServerDataBaseRecord(new KviIrcNetwork(__tr2qs("Standalone Servers")));
+ m_pRecords->replace(r->network()->name(),r);
+ }
+
+ KviIrcServer * s = new KviIrcServer();
+ s->m_szHostname = d->szServer;
+ if(bIsValidIpV4)
+ {
+ s->m_szIp = d->szServer;
+ s->setCacheIp(true);
+#ifdef COMPILE_IPV6_SUPPORT
+ } else {
+ if(bIsValidIpV6)
+ {
+ s->m_szIp = d->szServer;
+ s->setCacheIp(true);
+ d->bIpV6 = true;
+ }
+ }
+#else
+ }
+#endif
+ s->m_uPort = d->bPortIsValid ? d->uPort : 6667;
+ s->setLinkFilter(d->szLinkFilter);
+ s->m_szPass= d->szPass;
+ s->m_szNick= d->szNick;
+ s->m_szInitUMode = d->szInitUMode;
+ s->setIpV6(d->bIpV6);
+ s->setUseSSL(d->bSSL);
+ r->insertServer(s);
+ m_szCurrentNetwork = r->network()->name();
+ r->setCurrentServer(s);
+
+ return true;
+}
+
+void parseMircServerRecord(QString entry,QString& szNet,
+ QString& szDescription,QString& szHost,QString& szPort,bool& bSsl,kvi_u32_t& uPort)
+{
+ bSsl = false;
+ int idx = KviQString::find(entry,"SERVER:");
+ if(idx != -1)
+ {
+ szDescription = entry.left(idx);
+ szNet=szDescription.section(':',0,0);
+ szDescription=szDescription.section(':',1,1);
+
+ entry.remove(0,idx + 7);
+ idx = KviQString::find(entry,"GROUP:");
+ if(idx != -1)
+ {
+ szHost = entry.left(idx);
+ } else {
+ szHost = entry;
+ }
+
+ szPort = szHost.section(':',1,1);
+ if(szPort[0]=='+')
+ {
+ bSsl = true;
+ szPort.remove(0,1);
+ }
+ szHost = szHost.section(':',0,0);
+
+ bool bOk;
+ uPort = szPort.toUInt(&bOk);
+ if(!bOk)uPort = 6667;
+ }
+}
+
+void KviIrcServerDataBase::loadFromMircIni(const QString & filename, const QString & szMircIni, QStringList& recentServers)
+{
+ clear();
+ recentServers.clear();
+ QString szDefaultServer;
+ KviConfig mircCfg(szMircIni,KviConfig::Read,true);
+ if(mircCfg.hasGroup("mirc"))
+ {
+ mircCfg.setGroup("mirc");
+ szDefaultServer = mircCfg.readQStringEntry("host");
+ }
+
+ KviConfig cfg(filename,KviConfig::Read,true);
+ int i = 0;
+
+ QString entry;
+ QString key;
+ if(cfg.hasGroup("recent"))
+ {
+ cfg.setGroup("recent");
+ do {
+ KviQString::sprintf(key,"n%d",i);
+ entry = cfg.readEntry(key);
+ if(!entry.isEmpty())
+ {
+ QString szNet;
+ QString szDescription;
+ QString szHost;
+ QString szPort;
+ bool bSsl = false;
+ kvi_u32_t uPort = 0;
+
+ parseMircServerRecord(entry,szNet,
+ szDescription,szHost,szPort,bSsl,uPort);
+
+ recentServers << (bSsl ? "ircs://" : "irc://" ) +szHost+":"+szPort;
+ }
+ i++;
+ } while(!entry.isEmpty());
+ }
+
+ i = 0;
+ if(cfg.hasGroup("servers"))
+ {
+ cfg.setGroup("servers");
+ do {
+ KviQString::sprintf(key,"n%d",i);
+ entry = cfg.readEntry(key);
+ if(!entry.isEmpty())
+ {
+ bool bDefault = false;
+ QString szNet;
+ QString szDescription;
+ QString szHost;
+ QString szPort;
+ bool bSsl = false;
+ kvi_u32_t uPort = 0;
+ // <net>:<description>SERVER:<server:port>GROUP:<group???>
+ if(entry==szDefaultServer)
+ bDefault = true;
+
+ parseMircServerRecord(entry,szNet,
+ szDescription,szHost,szPort,bSsl,uPort);
+
+ KviIrcServerDataBaseRecord * r = findRecord(szNet);
+
+ if(!r) {
+ KviIrcNetwork * n = new KviIrcNetwork(szNet);
+ r = insertNetwork(n);
+ }
+
+ KviIrcServer *s = new KviIrcServer();
+ s->m_szHostname = szHost;
+ s->m_szDescription = szDescription;
+ s->m_uPort = uPort;
+
+
+ r->m_pServerList->append(s);
+ if(bDefault)
+ {
+ m_szCurrentNetwork = szNet;
+ }
+ }
+ i++;
+ } while(!entry.isEmpty());
+ }
+}
+
+
+void KviIrcServerDataBase::load(const QString & filename)
+{
+ clear();
+ KviConfig cfg(filename,KviConfig::Read);
+
+ KviConfigIterator it(*(cfg.dict()));
+
+ QString tmp;
+
+ while(it.current())
+ {
+ if(it.current()->count() > 0)
+ {
+ KviIrcNetwork * n = new KviIrcNetwork(it.currentKey());
+ KviIrcServerDataBaseRecord * r = insertNetwork(n);
+ cfg.setGroup(it.currentKey());
+ n->m_szEncoding = cfg.readQStringEntry("Encoding");
+ n->m_szDescription = cfg.readQStringEntry("Description");
+ n->m_szNickName = cfg.readQStringEntry("NickName");
+ n->m_szRealName = cfg.readQStringEntry("RealName");
+ n->m_szUserName = cfg.readQStringEntry("UserName");
+ n->m_szOnConnectCommand = cfg.readQStringEntry("OnConnectCommand");
+ n->m_szOnLoginCommand = cfg.readQStringEntry("OnLoginCommand");
+ n->m_pNickServRuleSet = KviNickServRuleSet::load(&cfg,QString::null);
+ n->m_bAutoConnect = cfg.readBoolEntry("AutoConnect",false);
+ n->m_szUserIdentityId = cfg.readQStringEntry("UserIdentityId");
+ if(n->m_bAutoConnect)
+ {
+ if(!m_pAutoConnectOnStartupNetworks)
+ {
+ m_pAutoConnectOnStartupNetworks = new KviPointerList<KviIrcServerDataBaseRecord>;
+ m_pAutoConnectOnStartupNetworks->setAutoDelete(false);
+ }
+ m_pAutoConnectOnStartupNetworks->append(r);
+ }
+ QStringList l = cfg.readStringListEntry("AutoJoinChannels",QStringList());
+ if(l.count() > 0)n->setAutoJoinChannelList(new QStringList(l));
+
+ if(cfg.readBoolEntry("Current",false))m_szCurrentNetwork = it.currentKey();
+
+ int nServers = cfg.readIntEntry("NServers",0);
+ for(int i=0;i < nServers;i++)
+ {
+ KviIrcServer *s = new KviIrcServer();
+ KviQString::sprintf(tmp,"%d_",i);
+ if(s->load(&cfg,tmp))
+ {
+ r->m_pServerList->append(s);
+ KviQString::sprintf(tmp,"%d_Current",i);
+ if(cfg.readBoolEntry(tmp,false))r->m_pCurrentServer = s;
+ if(s->autoConnect())
+ {
+ if(!m_pAutoConnectOnStartupServers)
+ {
+ m_pAutoConnectOnStartupServers = new KviPointerList<KviIrcServer>;
+ m_pAutoConnectOnStartupServers->setAutoDelete(false);
+ }
+ m_pAutoConnectOnStartupServers->append(s);
+ }
+ } else delete s;
+ }
+ if(!r->m_pCurrentServer)r->m_pCurrentServer = r->m_pServerList->first();
+ }
+ ++it;
+ }
+}
+
+void KviIrcServerDataBase::save(const QString &filename)
+{
+ KviConfig cfg(filename,KviConfig::Write);
+
+ cfg.clear(); // clear any old entry
+
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*m_pRecords);
+
+ QString tmp;
+
+ while(KviIrcServerDataBaseRecord * r = it.current())
+ {
+ KviIrcNetwork * n = r->network();
+ cfg.setGroup(n->m_szName);
+ cfg.writeEntry("NServers",r->m_pServerList->count());
+ if(n->m_bAutoConnect)
+ cfg.writeEntry("AutoConnect",true);
+ if(!n->m_szEncoding.isEmpty())
+ cfg.writeEntry("Encoding",n->m_szEncoding);
+ if(!n->m_szDescription.isEmpty())
+ cfg.writeEntry("Description",n->m_szDescription);
+ if(!n->m_szNickName.isEmpty())
+ cfg.writeEntry("NickName",n->m_szNickName);
+ if(!n->m_szRealName.isEmpty())
+ cfg.writeEntry("RealName",n->m_szRealName);
+ if(!n->m_szUserName.isEmpty())
+ cfg.writeEntry("UserName",n->m_szUserName);
+ if(!n->m_szOnConnectCommand.isEmpty())
+ cfg.writeEntry("OnConnectCommand",n->m_szOnConnectCommand);
+ if(!n->m_szOnLoginCommand.isEmpty())
+ cfg.writeEntry("OnLoginCommand",n->m_szOnLoginCommand);
+ if(n->m_pNickServRuleSet)n->m_pNickServRuleSet->save(&cfg,QString::null);
+ if(n->autoJoinChannelList())
+ cfg.writeEntry("AutoJoinChannels",*(n->autoJoinChannelList()));
+ if(n->m_szName == m_szCurrentNetwork)cfg.writeEntry("Current",true);
+ if(!n->m_szUserIdentityId.isEmpty())
+ cfg.writeEntry("UserIdentityId",n->m_szUserIdentityId);
+ int i=0;
+ for(KviIrcServer *s = r->m_pServerList->first();s;s = r->m_pServerList->next())
+ {
+ KviQString::sprintf(tmp,"%d_",i);
+ s->save(&cfg,tmp);
+
+ if(s == r->m_pCurrentServer)
+ {
+ KviQString::sprintf(tmp,"%d_Current",i);
+ cfg.writeEntry(tmp,true);
+ }
+
+ i++;
+ }
+ ++it;
+ }
+}
+
+
+
diff --git a/src/kvilib/irc/kvi_ircserverdb.h b/src/kvilib/irc/kvi_ircserverdb.h
new file mode 100644
index 00000000..b5d55231
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircserverdb.h
@@ -0,0 +1,116 @@
+#ifndef _KVI_IRCSERVERDB_H_
+#define _KVI_IRCSERVERDB_H_
+//=============================================================================
+//
+// File : kvi_ircserverdb.h
+// Creation date : Mon Jul 10 2000 14:15:42 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_ircserver.h"
+
+#include "kvi_pointerhashtable.h"
+
+typedef struct _KviIrcServerDefinition
+{
+ QString szServer;
+ kvi_u32_t uPort;
+ bool bPortIsValid;
+ bool bIpV6;
+ bool bSSL;
+ QString szLinkFilter;
+ QString szPass;
+ QString szNick;
+ QString szInitUMode;
+} KviIrcServerDefinition;
+
+
+
+class KVILIB_API KviIrcServerDataBaseRecord
+{
+ friend class KviIrcServerDataBase;
+public:
+ KviIrcServerDataBaseRecord(KviIrcNetwork * n);
+ ~KviIrcServerDataBaseRecord();
+protected:
+ KviIrcNetwork * m_pNetwork;
+ KviPointerList<KviIrcServer> * m_pServerList;
+
+ KviIrcServer * m_pCurrentServer;
+public:
+ KviIrcNetwork * network(){ return m_pNetwork; };
+ KviPointerList<KviIrcServer> * serverList(){ return m_pServerList; };
+ KviIrcServer * currentServer();
+ void insertServer(KviIrcServer *srv);
+ KviIrcServer * findServer(const KviIrcServer * pServer);
+ void setCurrentServer(KviIrcServer *srv);
+};
+
+
+
+
+
+class KVILIB_API KviIrcServerDataBase
+{
+public:
+ KviIrcServerDataBase();
+ ~KviIrcServerDataBase();
+private:
+ KviPointerHashTable<QString,KviIrcServerDataBaseRecord> * m_pRecords;
+ QString m_szCurrentNetwork;
+ // This list is computed when the data are loaded from disk
+ // during the startup and is used by KviApp to
+ // start the connections.
+ // The pointer is zero if there are no autoConnect servers
+ // The list is valid only during the startup phase
+ // because it contains shallow pointers to the servers
+ // really contained in the server/network list
+ // and it is never updated later
+ KviPointerList<KviIrcServer> * m_pAutoConnectOnStartupServers;
+ KviPointerList<KviIrcServerDataBaseRecord> * m_pAutoConnectOnStartupNetworks;
+public:
+ void clear();
+ KviPointerHashTable<QString,KviIrcServerDataBaseRecord> * recordDict(){ return m_pRecords; };
+ KviPointerList<KviIrcServer> * autoConnectOnStartupServers(){ return m_pAutoConnectOnStartupServers; };
+ KviPointerList<KviIrcServerDataBaseRecord> * autoConnectOnStartupNetworks(){ return m_pAutoConnectOnStartupNetworks; };
+ void clearAutoConnectOnStartupServers();
+ void clearAutoConnectOnStartupNetworks();
+ void setCurrentNetwork(const QString &szNetName){ m_szCurrentNetwork = szNetName; };
+ const QString & currentNetworkName(){ return m_szCurrentNetwork; };
+ KviIrcServerDataBaseRecord * currentRecord();
+ KviIrcServerDataBaseRecord * findRecord(const QString &szNetName);
+ KviIrcNetwork * findNetwork(const QString &name);
+ void loadFromMircIni(const QString & filename, const QString & szMircIni, QStringList& recentServers);
+ void load(const QString & filename);
+ void save(const QString & filename);
+ KviIrcServerDataBaseRecord * insertNetwork(KviIrcNetwork * n);
+ void updateServerIp(KviIrcServer * pServer,const QString &ip);
+ bool makeCurrentServer(KviIrcServerDefinition * d,QString &szError);
+ bool makeCurrentBestServerInNetwork(const QString &szNetName,KviIrcServerDataBaseRecord * d,QString &szError);
+};
+
+
+
+
+
+
+#endif //_KVI_IRCSERVERDB_H_
diff --git a/src/kvilib/irc/kvi_ircuserdb.cpp b/src/kvilib/irc/kvi_ircuserdb.cpp
new file mode 100644
index 00000000..38b52522
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircuserdb.cpp
@@ -0,0 +1,285 @@
+//=============================================================================
+//
+// File : kvi_ircuserdb.cpp
+// Creation date : Mon Jul 31 2000 21:23:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_debug.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_qstring.h"
+#include "kvi_stringconversion.h"
+
+//static int cacheHit = 0;
+//static int cacheMiss = 0;
+
+KviIrcUserEntry::KviIrcUserEntry(const QString &user,const QString &host)
+{
+ m_szUser = user;
+ m_szHost = host;
+ m_pAvatar = 0;
+ m_nRefs = 1;
+ m_iHops = -1;
+ m_bAway = false;
+ m_eGender = Unknown;
+ m_bBot = false;
+ m_bNotFoundRegUserLoockup=false;
+ m_bUseCustomColor=false;
+}
+
+void KviIrcUserEntry::setRealName(const QString &rn)
+{
+ m_szRealName = rn;
+ m_szRealName = KviQString::trimmed(m_szRealName);
+ if(m_szRealName.length()>=3)
+ {
+ if( (m_szRealName[0].unicode()==KVI_TEXT_COLOR) && (m_szRealName[2].unicode()==KVI_TEXT_RESET) )
+ {
+ switch(m_szRealName[1].unicode())
+ {
+ case '1': // hum.. encoded as hidden color code eh ? publish is somewhere, so others might implement this...
+ setGender(Male);
+ break;
+ case '2':
+ setGender(Female);
+ break;
+ case '3':
+ setBot(true);
+ break;
+ }
+ m_szRealName.remove(0,3);
+ }
+ }
+}
+
+KviIrcUserEntry::~KviIrcUserEntry()
+{
+ if(m_pAvatar)delete m_pAvatar;
+}
+
+void KviIrcUserEntry::setAvatar(KviAvatar * av)
+{
+ if(m_pAvatar)delete m_pAvatar;
+ m_pAvatar = av;
+}
+
+KviAvatar * KviIrcUserEntry::forgetAvatar()
+{
+ KviAvatar * ret = m_pAvatar;
+ m_pAvatar = 0;
+ return ret;
+}
+
+KviIrcUserDataBase::KviIrcUserDataBase()
+: QObject()
+{
+ // we expect a maximum of ~4000 users (= ~16 KB array on a 32 bit machine)
+ // ...after that we will loose in performance
+ // ... well...4000 users is a really big number...say 6-7 really big channels
+ // (4001 is prime)
+ // up to 12000 users we will have a reasonably fast access.
+ // the performance increase since kvirc versions < 3.0.0
+ // is really big anyway (there was a linear list instead of a hash!!!)
+
+ m_pDict = new KviPointerHashTable<QString,KviIrcUserEntry>(4001,false);
+ m_pDict->setAutoDelete(true);
+ setupConnectionWithReguserDb();
+}
+
+KviIrcUserDataBase::~KviIrcUserDataBase()
+{
+ delete m_pDict;
+}
+
+bool KviIrcUserDataBase::haveCustomColor(const QString & nick)
+{
+ KviIrcUserEntry *u = find(nick);
+ if(!u) return false;
+ if( u->m_szLastRegisteredMatchNick!=nick)
+ registeredUser(nick);
+ if(!u->m_bNotFoundRegUserLoockup)
+ {
+ return u->m_bUseCustomColor;
+ }
+ return false;
+}
+
+QColor* KviIrcUserDataBase::customColor(const QString & nick)
+{
+ KviIrcUserEntry *u = find(nick);
+ if(!u) return 0;
+ if( u->m_szLastRegisteredMatchNick!=nick)
+ registeredUser(nick);
+
+ if(!u->m_bNotFoundRegUserLoockup)
+ {
+ return &(u->m_cachedColor);
+ }
+ return 0;
+}
+
+
+KviRegisteredUser* KviIrcUserDataBase::registeredUser(const QString & nick,const QString & user,const QString & host)
+{
+ if(nick.isEmpty()) return 0;
+ KviIrcUserEntry *u = find(nick);
+ if(!u) return g_pRegisteredUserDataBase->findMatchingUser(nick,user,host);
+ KviRegisteredUser* pUser=0;
+
+ if(u->m_bNotFoundRegUserLoockup && u->m_szLastRegisteredMatchNick==nick)
+ {
+ //cacheHit++;
+ //debug("cache hits/miss = %i/%i",cacheHit,cacheMiss);
+ return 0;
+ }
+
+ if(!u->m_szRegisteredUserName.isEmpty() && u->m_szLastRegisteredMatchNick==nick)
+ {
+ pUser = g_pRegisteredUserDataBase->getUser(u->m_szRegisteredUserName);
+ //if(pUser) cacheHit++;
+ }
+
+ if(!pUser) {
+ //user renamed or it is a first loockup
+ if(u->hasHost() && u->hasUser())
+ {
+ pUser=g_pRegisteredUserDataBase->findMatchingUser(nick,u->user(),u->host());
+ //cacheMiss++;
+ if(pUser) {
+ u->m_szLastRegisteredMatchNick=nick;
+ u->m_szRegisteredUserName=pUser->name();
+
+ u->m_bUseCustomColor=pUser->getBoolProperty("useCustomColor");
+ QString szTmp=pUser->getProperty("customColor");
+ KviStringConversion::fromString(szTmp,u->m_cachedColor);
+
+ u->m_bNotFoundRegUserLoockup=false; //to be shure
+ } else {
+ u->m_szLastRegisteredMatchNick=nick;
+ u->m_bNotFoundRegUserLoockup=true;
+ }
+ }
+ }
+
+// debug("cache hits/miss = %i/%i",cacheHit,cacheMiss);
+ return pUser;
+}
+
+KviRegisteredUser* KviIrcUserDataBase::registeredUser(const QString & nick)
+{
+ if(nick.isEmpty()) return 0;
+ KviIrcUserEntry *u = find(nick);
+ if(!u) return 0;
+ return registeredUser(nick,u->user(),u->host());
+}
+
+void KviIrcUserDataBase::clear()
+{
+ delete m_pDict;
+ m_pDict = new KviPointerHashTable<QString,KviIrcUserEntry>(4001,false);
+ m_pDict->setAutoDelete(true);
+}
+
+KviIrcUserEntry * KviIrcUserDataBase::insertUser(const QString &nick,const QString &user,const QString &hostname)
+{
+ KviIrcUserEntry * e = m_pDict->find(nick);
+ if(e)
+ {
+ e->m_nRefs++;
+ if(e->m_szUser.isEmpty())
+ {
+ e->m_szUser = user;
+ e->m_szHost = hostname;
+ }
+ } else {
+ e = new KviIrcUserEntry(user,hostname);
+ m_pDict->insert(nick,e);
+ }
+ return e;
+}
+
+void KviIrcUserDataBase::removeUser(const QString &nick,KviIrcUserEntry * e)
+{
+ e->m_nRefs--;
+ if(e->m_nRefs == 0)m_pDict->remove(nick);
+}
+
+void KviIrcUserDataBase::setupConnectionWithReguserDb()
+{
+ connect(g_pRegisteredUserDataBase,SIGNAL(userRemoved(const QString&)),this,SLOT(registeredUserRemoved(const QString&)));
+ connect(g_pRegisteredUserDataBase,SIGNAL(userChanged(const QString&)),this,SLOT(registeredUserChanged(const QString&)));
+ connect(g_pRegisteredUserDataBase,SIGNAL(userAdded(const QString&)),this,SLOT(registeredUserAdded(const QString&)));
+ connect(g_pRegisteredUserDataBase,SIGNAL(databaseCleared()),this,SLOT(registeredDatabaseCleared()));
+
+
+}
+
+void KviIrcUserDataBase::registeredUserRemoved(const QString& user)
+{
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it( *m_pDict );
+ for( ; it.current(); ++it )
+ {
+ if(it.current()->m_szRegisteredUserName==user)
+ {
+ it.current()->m_szRegisteredUserName="";
+ it.current()->m_bNotFoundRegUserLoockup=false;
+ }
+ }
+}
+
+void KviIrcUserDataBase::registeredUserChanged(const QString& user)
+{
+ //the same as above
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it( *m_pDict );
+ for( ; it.current(); ++it )
+ {
+ if(it.current()->m_szRegisteredUserName==user)
+ {
+ it.current()->m_szRegisteredUserName="";
+ it.current()->m_bNotFoundRegUserLoockup=false;
+ }
+ }
+}
+
+void KviIrcUserDataBase::registeredUserAdded(const QString& user)
+{
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it( *m_pDict );
+ for( ; it.current(); ++it )
+ {
+ if(it.current()->m_szRegisteredUserName.isEmpty())
+ {
+ it.current()->m_bNotFoundRegUserLoockup=false;
+ }
+ }
+}
+
+void KviIrcUserDataBase::registeredDatabaseCleared()
+{
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it( *m_pDict );
+ for( ; it.current(); ++it )
+ {
+ it.current()->m_szRegisteredUserName="";
+ it.current()->m_bNotFoundRegUserLoockup=false;
+ }
+}
diff --git a/src/kvilib/irc/kvi_ircuserdb.h b/src/kvilib/irc/kvi_ircuserdb.h
new file mode 100644
index 00000000..bdf7c51c
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircuserdb.h
@@ -0,0 +1,145 @@
+#ifndef _KVI_IRCUSERDB_H_
+#define _KVI_IRCUSERDB_H_
+
+//=============================================================================
+//
+// File : kvi_ircuserdb.h
+// Creation date : Mon Jul 31 2000 20:59:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_pointerhashtable.h"
+
+#include "kvi_string.h"
+#include "kvi_avatar.h"
+#include "kvi_regusersdb.h"
+
+class KviIrcUserDataBase;
+
+class KVILIB_API KviIrcUserEntry
+{
+ friend class KviIrcUserDataBase;
+public:
+ KviIrcUserEntry(const QString &user,const QString &host);
+ ~KviIrcUserEntry();
+
+ enum Gender {
+ Male = 0,
+ Female = 1,
+ Unknown = 3
+ };
+
+protected:
+ QString m_szUser;
+ QString m_szHost;
+
+ QString m_szServer;
+ QString m_szRealName;
+ int m_iHops;
+ Gender m_eGender;
+
+ bool m_bAway;
+
+ KviAvatar * m_pAvatar;
+
+ int m_nRefs;
+ bool m_bBot;
+
+ bool m_bNotFoundRegUserLoockup;
+ QString m_szRegisteredUserName;
+ QString m_szLastRegisteredMatchNick;
+
+ QColor m_cachedColor;
+ bool m_bUseCustomColor;
+public:
+ Gender gender() { return m_eGender; };
+ void setBot(bool bIsBot) { m_bBot = bIsBot; };
+ bool isBot() { return m_bBot; };
+ void setGender(Gender g) { m_eGender=g; };
+ void setUser(const QString &user) { m_szUser = user; };
+ bool hasUser() { return (!m_szUser.isEmpty()); };
+ void setHost(const QString &host) { m_szHost = host; };
+ bool hasHost() { return (!m_szHost.isEmpty()); };
+ void setServer(const QString &serv) { m_szServer = serv; };
+ void setRealName(const QString &rn);
+ void setHops(int hops) { m_iHops = hops; };
+ const QString &user() { return m_szUser; };
+ const QString &host() { return m_szHost; };
+ bool hasServer() { return (!m_szServer.isEmpty()); };
+ const QString &server() { return m_szServer; };
+ bool hasRealName() { return (!m_szRealName.isEmpty()); };
+ const QString &realName() { return m_szRealName; };
+ bool hasHops() { return m_iHops >= 0; };
+ int hops() { return m_iHops; };
+ KviAvatar * avatar() { return m_pAvatar; };
+ int nRefs() { return m_nRefs; };
+ bool isAway() const { return m_bAway; };
+ void setAway(bool bAway) { m_bAway = bAway; };
+ // warning! the ownership passes to this class!
+ void setAvatar(KviAvatar * av = 0);
+ KviAvatar * forgetAvatar();
+};
+
+// from least powerful to most powerful
+#define KVI_USERFLAG_USEROP 1
+#define KVI_USERFLAG_VOICE 2
+#define KVI_USERFLAG_HALFOP 4
+#define KVI_USERFLAG_OP 8
+#define KVI_USERFLAG_CHANADMIN 16
+#define KVI_USERFLAG_CHANOWNER 32
+
+// 1 | 2 | 4 | 8 | 16 | 32
+#define KVI_USERFLAG_MASK (KVI_USERFLAG_OP | KVI_USERFLAG_VOICE | KVI_USERFLAG_HALFOP | KVI_USERFLAG_CHANADMIN | KVI_USERFLAG_USEROP | KVI_USERFLAG_CHANOWNER)
+// at the moment all the flags are usermodes
+#define KVI_USERFLAG_MODEMASK KVI_USERFLAG_MASK
+
+
+class KVILIB_API KviIrcUserDataBase : public QObject
+{
+ Q_OBJECT
+public:
+ KviIrcUserDataBase();
+ ~KviIrcUserDataBase();
+private:
+ KviPointerHashTable<QString,KviIrcUserEntry> * m_pDict;
+public:
+ void clear();
+ KviIrcUserEntry * insertUser(const QString &nick,const QString &user,const QString &hostname);
+ KviIrcUserEntry * find(const QString &nick){ return m_pDict->find(nick); };
+ void removeUser(const QString &nick,KviIrcUserEntry * e);
+ KviPointerHashTable<QString,KviIrcUserEntry> * dict(){ return m_pDict; };
+
+ KviRegisteredUser* registeredUser(const QString & nick);
+ KviRegisteredUser* registeredUser(const QString & nick,const QString & user,const QString & host);
+
+ bool haveCustomColor(const QString & nick);
+ QColor* customColor(const QString & nick);
+
+ void setupConnectionWithReguserDb();
+protected slots:
+ void registeredUserRemoved(const QString&);
+ void registeredUserChanged(const QString&);
+ void registeredUserAdded (const QString&);
+ void registeredDatabaseCleared();
+};
+
+#endif //_KVI_IRCUSERDB_H_
diff --git a/src/kvilib/irc/kvi_mirccntrl.cpp b/src/kvilib/irc/kvi_mirccntrl.cpp
new file mode 100644
index 00000000..fbf3c2d3
--- /dev/null
+++ b/src/kvilib/irc/kvi_mirccntrl.cpp
@@ -0,0 +1,307 @@
+//
+// File : kvi_mirccntrl.cpp
+// Creation date : Sat Aug 31 17:07:36 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#define __KVILIB__
+
+#define _KVI_MIRCCNTRL_CPP_
+
+#include "kvi_mirccntrl.h"
+
+KVILIB_API const char * getColorBytes(const char *data_ptr,unsigned char *byte_1,unsigned char *byte_2)
+{
+ //
+ // Scans the data_ptr for a mIrc color code XX,XX
+ // and fills the color values in the two bytes
+ //
+
+ //First we can have a digit or a coma
+ if(((*data_ptr >= '0') && (*data_ptr <='9')))
+ {
+ //Something interesting ok.
+ (*byte_1)=(*data_ptr)-'0'; //store the code
+ data_ptr++; //and check the next
+ if(((*data_ptr >= '0') && (*data_ptr <= '9'))||(*data_ptr==','))
+ {
+ //Yes we can understand it
+ if(*data_ptr==',')
+ {
+ //A coma , need to check for background
+ data_ptr++;
+ } else {
+ //A number
+ (*byte_1)=((((*byte_1)*10)+((*data_ptr)-'0'))%16);
+ data_ptr++;
+ if(*data_ptr==',')
+ {
+ //A coma , need to check for background
+ data_ptr++;
+ } else {
+ //Senseless return
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+ }
+ } else {
+ //Senseless character control code OK and return
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+ } else {
+ //Senseless character : only a CTRL+K code
+ (*byte_1)=KVI_NOCHANGE;
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+
+ if((*data_ptr >= '0') && (*data_ptr <='9'))
+ {
+ //Background , a color code
+ (*byte_2)=(*data_ptr)-'0';
+ data_ptr++;
+ if((*data_ptr >= '0') && (*data_ptr <='9'))
+ {
+ (*byte_2)=((((*byte_2)*10)+((*data_ptr)-'0'))%16);
+ data_ptr++;
+ }
+ return data_ptr;
+ } else {
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr-1;
+ }
+}
+
+
+KVILIB_API const kvi_wchar_t * getColorBytesW(const kvi_wchar_t *data_ptr,unsigned char *byte_1,unsigned char *byte_2)
+{
+ //
+ // Scans the data_ptr for a mIrc color code XX,XX
+ // and fills the color values in the two bytes
+ //
+
+ //First we can have a digit or a coma
+ if(((*data_ptr >= '0') && (*data_ptr <='9')))
+ {
+ //Something interesting ok.
+ (*byte_1)=((*data_ptr)-'0'); //store the code
+ data_ptr++; //and check the next
+ if(((*data_ptr >= '0') && (*data_ptr <= '9'))||(*data_ptr==','))
+ {
+ //Yes we can understand it
+ if(*data_ptr==',')
+ {
+ //A coma , need to check for background
+ data_ptr++;
+ } else {
+ //A number
+ //(*byte_1)=((((*byte_1)*10)+((*data_ptr)-'0'))%16);
+ (*byte_1)=((*byte_1)*10)+((*data_ptr)-'0');
+ data_ptr++;
+ if(*data_ptr==',')
+ {
+ //A coma , need to check for background
+ data_ptr++;
+ } else {
+ //Senseless return
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+ }
+ } else {
+ //Senseless character control code OK and return
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+ } else {
+ //Senseless character : only a CTRL+K code
+ (*byte_1)=KVI_NOCHANGE;
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+
+ if((*data_ptr >= '0') && (*data_ptr <='9'))
+ {
+ //Background , a color code
+ (*byte_2)=(*data_ptr)-'0';
+ data_ptr++;
+ if((*data_ptr >= '0') && (*data_ptr <='9'))
+ {
+ //(*byte_2)=((((*byte_2)*10)+((*data_ptr)-'0'))%16);
+ (*byte_2)=((*byte_2)*10)+((*data_ptr)-'0');
+ data_ptr++;
+ }
+ return data_ptr;
+ } else {
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr-1;
+ }
+}
+
+KVILIB_API unsigned int getUnicodeColorBytes(const QString &szData,unsigned int charIdx,unsigned char *byte_1,unsigned char *byte_2)
+{
+ //
+ // Scans the szData for a mIrc color code XX,XX
+ // and fills the color values in the two bytes
+ //
+
+ if(charIdx >= szData.length())
+ {
+ (*byte_1)=KVI_NOCHANGE;
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+ unsigned short c = szData[(int)charIdx].unicode();
+
+ //First we can have a digit or a coma
+ if(((c < '0') || (c > '9')))
+ {
+ // senseless : only a CTRL+K code
+ (*byte_1)=KVI_NOCHANGE;
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+ //Something interesting ok.
+ (*byte_1)=c - '0'; //store the code
+ charIdx++;
+ if(charIdx >= szData.length())
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+ c = szData[(int)charIdx].unicode();
+
+ if(((c < '0') || (c > '9')) && (c != ','))
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+
+ if((c >= '0') && (c <= '9'))
+ {
+ (*byte_1)=(((*byte_1)*10)+(c-'0'))%16;
+ charIdx++;
+ if(charIdx >= szData.length())
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+ c = szData[(int)charIdx].unicode();
+ }
+
+ if(c == ',')
+ {
+ charIdx++;
+ if(charIdx >= szData.length())
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+ c = szData[(int)charIdx].unicode();
+ } else {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+ if((c < '0') || (c > '9'))
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ if(szData[(int)(charIdx-1)].unicode()==',')
+ return charIdx-1;
+ else
+ return charIdx;
+ }
+
+ //Background , a color code
+ (*byte_2)=c-'0';
+ charIdx++;
+ if(charIdx >= szData.length())return charIdx;
+ c = szData[(int)charIdx].unicode();
+
+ if((c >= '0') && (c <='9'))
+ {
+ (*byte_2)=(((*byte_2)*10)+(c-'0'))%16;
+ charIdx++;
+ }
+
+ return charIdx;
+}
+
+
+namespace KviMircCntrl
+{
+ QString stripControlBytes(const QString &szData)
+ {
+ QString ret;
+
+ int i = 0;
+ int l = szData.length();
+ int begin = 0;
+ unsigned char b1;
+ unsigned char b2;
+ while(i < l)
+ {
+ switch(szData[i].unicode())
+ {
+ case KVI_TEXT_UNDERLINE:
+ case KVI_TEXT_BOLD:
+ case KVI_TEXT_RESET:
+ case KVI_TEXT_REVERSE:
+ case KVI_TEXT_CRYPTESCAPE:
+ case KVI_TEXT_CTCP:
+ if(i != begin)
+ ret += szData.mid(begin,i - begin);
+ i++;
+ begin = i;
+ break;
+ case KVI_TEXT_COLOR:
+ if(i != begin)
+ ret += szData.mid(begin,i - begin);
+ i++;
+ i = getUnicodeColorBytes(szData,i,&b1,&b2);
+ begin = i;
+ break;
+ case KVI_TEXT_ICON:
+ if(i != begin)
+ ret += szData.mid(begin,i - begin);
+ i++;
+ while(i < l)
+ {
+ if(szData[i].unicode() == ' ')break;
+ else i++;
+ }
+ begin = i;
+ break;
+ default:
+ i++;
+ break;
+ }
+ }
+ if(i != begin)
+ ret += szData.mid(begin,i - begin);
+ return ret;
+ }
+}
+
+
diff --git a/src/kvilib/irc/kvi_mirccntrl.h b/src/kvilib/irc/kvi_mirccntrl.h
new file mode 100644
index 00000000..c3028568
--- /dev/null
+++ b/src/kvilib/irc/kvi_mirccntrl.h
@@ -0,0 +1,163 @@
+#ifndef _KVI_MIRCCNTRL_H_
+#define _KVI_MIRCCNTRL_H_
+
+//=============================================================================
+//
+// File : kvi_mirccntrl.h
+// Creation date : Thu Jun 29 2000 21:06:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+//=============================================================================
+// This file contains non-customizable standards
+//
+// Better do not touch this :)
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+
+//
+// mIrc color codes
+//
+
+#define KVI_WHITE 0
+#define KVI_BLACK 1
+#define KVI_DARKBLUE 2
+#define KVI_DARKGREEN 3
+#define KVI_RED 4
+#define KVI_DARKRED 5
+#define KVI_DARKVIOLET 6
+#define KVI_ORANGE 7
+#define KVI_YELLOW 8
+#define KVI_LIGHTGREEN 9
+#define KVI_BLUEMARINE 10
+#define KVI_LIGHTBLUE 11
+#define KVI_BLUE 12
+#define KVI_LIGHTVIOLET 13
+#define KVI_DARKGRAY 14
+#define KVI_LIGHTGRAY 15
+
+#define KVI_MIRCCOLOR_MAX_FOREGROUND 15
+#define KVI_MIRCCOLOR_MAX_BACKGROUND 15
+
+//
+// Non-standard color codes for KviIrcView
+//
+#define KVI_TRANSPARENT 100
+#define KVI_NOCHANGE 101
+//
+// Internal control codes for KviIrcView
+//
+// (Totally artificial and internal to KviIrcView)
+#define KVI_TEXT_ESCAPE 0x04
+#define KVI_TEXT_UNESCAPE 0x05
+#define KVI_TEXT_UNICON 0x06
+//#define KVI_TEXT_EMOTICON 0x07
+
+// ASCII Stuff: the following defines are meant to be escape sequences
+// that can go thru an IRC connection
+
+// The following table is a 30-minute analysis of the escape characters commonly used over the IRC protocol...
+// created when looking for a good placement for the CRYPT escape char in KVirc.
+// I guess that the best chars to be used were FS,GS,RS,US,DC1,DC2,DC3,DC4...they have the "less defined"
+// meaning as ASCII control chars.
+// mmmh... :)
+
+// ASCII IRC Meaning
+// 000 NUL Null (Cannot be assigned)
+// 001 SOH Start of heading ( CTCP Escape: only beginning of the message )
+// 002 STX Start of text ( Bold text )
+// 003 ETX End of text ( Color text escape sequence )
+// 004 EOT End of transmission ( Assigned internally (escape) )
+// 005 ENQ Enquiry (WRU: Who are you) ( Assigned internally (unescape) )
+// 006 ACK Acknowledge (Not so good, but can be used as last resource)
+// 007 BEL Bell ( Recognized as bell by terminals and IRCII ) (Used also by some IRC servers)
+// 008 BS Backspace (Should not be assigned: terminal control)
+// 009 HT Horizontal tabulation (Should not be assigned: terminal control)
+// 010 LF Line feed (Should not be assigned: terminal control)
+// 011 VT Vertical tabulation (Should not be assigned: terminal control)
+// 012 FF Form feed (Should not be assigned: terminal control)
+// 013 CR Carriage return (Should not be assigned: terminal control)
+// 014 SO Shift out (Should not be assigned: terminal control)
+// 015 SI Shift in ( Resets Bold,Color,Underline and Reverse ) (Conflicting with terminal control)
+// 016 DLE Data link escape (Decent , can be assigned)
+// 017 DC1 Device control 1 (Good to be assigned)
+// 018 DC2 Device control 2 (Good to be assigned)
+// 019 DC3 Device control 3 (Good to be assigned)
+// 020 DC4 Device control 4 (Good to be assigned)
+// 021 NAK Negative acknowledge (Not so good, but could be used as last resource)
+// 022 SYN Synchronous idle ( Reverse text )
+// 023 ETB End of transmission block (Decent , can be assigned)
+// 024 CAN Cancel (Should not be assigned: terminal control)
+// 025 EM End of medium (Decent , can be assigned)
+// 026 SUB Substitute (Should not be assigned: terminal control)
+// 027 ESC Escape (Should not be assigned: terminal control)
+// 028 FS File separator (Excellent , should be used as first candidate)
+// 029 GS Group separator ( ICONS Escape: beginning of a word )
+// 030 RS Record separator ( CRYPT Escape: only beginning of the message )
+// 031 US Unit separator ( Underline text )
+
+
+//
+// mIrc control codes
+//
+
+//31 (0001 1111) US (Unit separator)
+#define KVI_TEXT_UNDERLINE 0x1f
+//2 (0000 0010) STX (Start of text)
+#define KVI_TEXT_BOLD 0x02
+//15 (0000 1111) SI (Shift in)
+#define KVI_TEXT_RESET 0x0f
+//22 (0001 0110) SYN (Synchronous idle)
+#define KVI_TEXT_REVERSE 0x16
+//3 (0000 0011) ETX (End of text)
+#define KVI_TEXT_COLOR 0x03
+
+//
+// Irc control codes
+//
+//1 (0000 0001) SOH (Start of heading)
+#define KVI_TEXT_CTCP 0x01
+
+//
+// KVirc added control codes
+//
+//30 (0001 1110) RS (Record separator)
+#define KVI_TEXT_CRYPTESCAPE 0x1e
+//29 (0001 1101) GS (Group separator)
+#define KVI_TEXT_ICON 0x1d
+
+#ifndef _KVI_MIRCCNTRL_CPP_
+ extern KVILIB_API const char * getColorBytes(const char *data_ptr,unsigned char *byte_1,unsigned char *byte_2);
+ extern KVILIB_API const kvi_wchar_t * getColorBytesW(const kvi_wchar_t *data_ptr,unsigned char *byte_1,unsigned char *byte_2);
+ extern KVILIB_API unsigned int getUnicodeColorBytes(const QString &szData,unsigned int charIdx,unsigned char *byte_1,unsigned char *byte_2);
+ inline const QChar * getUnicodeColorBytes(const QChar *pData,unsigned char *byte_1,unsigned char *byte_2)
+ { return (QChar *)getColorBytesW((const kvi_wchar_t *)pData,byte_1,byte_2); };
+
+#endif
+
+namespace KviMircCntrl
+{
+ KVILIB_API QString stripControlBytes(const QString &szData);
+}
+
+
+#endif //_KVI_MIRCCNTRL_H_
diff --git a/src/kvilib/irc/kvi_nickserv.cpp b/src/kvilib/irc/kvi_nickserv.cpp
new file mode 100644
index 00000000..a1809f84
--- /dev/null
+++ b/src/kvilib/irc/kvi_nickserv.cpp
@@ -0,0 +1,312 @@
+//=============================================================================
+//
+// File : kvi_nickserv.cpp
+// Creation date : Thu Aug 09 2001 17:44:56 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_nickserv.h"
+#include "kvi_config.h"
+#include "kvi_ircmask.h"
+
+#include <qregexp.h>
+
+
+
+/*
+ @doc: nickserv_proto
+ @title:
+ Authentication with NickServ
+ @keyterms:
+ NickServ, automatic authentication with NickServ
+ @type:
+ generic
+ @short:
+ Automatic authentication with NickServ
+ @body:
+ KVIrc supports automatic authentication with the NickServ service.[br]
+ This service is commonly implemented on major IRC networks: basically
+ it is a program that allows users to register their nickname and protect
+ it from being stolen by others.[br] The NickServ protocol is
+ not standardized (at the time that I'm writing this doc) and automatic
+ authentication is a pure experimental protocol.[br]
+ Once you get on IRC with a registered nickname , the NickServ will
+ ask you for identification by sending you a NOTICE.[br]
+ The message will look in a way similar to the following:[br]
+ <b>You're using a registered nickname: if this is your nick,
+ please type /msg NickServ IDENTIFY password, otherwise please
+ choose another nickname</b>.[br]
+ The message is often broken in two or three lines of text.[br]
+ Please note that many network policies suggest to avoid automatic authentication
+ with NickServ.[br]I have implemented it because I know that it works on the networks
+ that I'm usually on.[br]You have to check that this protocol works on your network and
+ then eventually use it at your own risk.[br]
+*/
+
+
+// FIXME: The doc above is a bit outdated , fix it
+
+KviNickServRuleSet::KviNickServRuleSet()
+: KviHeapObject()
+{
+ m_bEnabled = false;
+ m_pRules = 0;
+}
+
+KviNickServRuleSet::KviNickServRuleSet(const KviNickServRuleSet &s)
+{
+ m_pRules = 0;
+ copyFrom(s);
+}
+
+
+KviNickServRuleSet::~KviNickServRuleSet()
+{
+ if(m_pRules)delete m_pRules;
+}
+
+void KviNickServRuleSet::save(KviConfig * cfg,const QString &prefix)
+{
+ if(!m_pRules)return; // nothing to save
+ if(m_pRules->isEmpty())return; // should never happen anyway
+ QString tmp;
+ if(m_bEnabled)
+ {
+ KviQString::sprintf(tmp,"%QNSEnabled",&prefix);
+ cfg->writeEntry(tmp,m_bEnabled);
+ }
+ KviQString::sprintf(tmp,"%QNSRules",&prefix);
+ cfg->writeEntry(tmp,m_pRules->count());
+ int idx = 0;
+ for(KviNickServRule * r = m_pRules->first();r;r = m_pRules->next())
+ {
+ KviQString::sprintf(tmp,"%QNSRule%d_",&prefix,idx);
+ r->save(cfg,tmp);
+ idx++;
+ }
+}
+
+KviNickServRuleSet * KviNickServRuleSet::load(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QNSRules",&prefix);
+ unsigned int cnt = cfg->readUIntEntry(tmp,0);
+ if(cnt == 0)return 0;
+ KviNickServRuleSet * s = new KviNickServRuleSet();
+ if(s->loadPrivate(cfg,prefix,cnt))return s;
+ delete s;
+ return 0;
+}
+
+void KviNickServRuleSet::load(const QString &szConfigFile)
+{
+ clear();
+ KviConfig cfg(szConfigFile,KviConfig::Read);
+
+ QString tmp;
+ KviQString::sprintf(tmp,"NSRules");
+ unsigned int cnt = cfg.readUIntEntry(tmp,0);
+ if(cnt == 0)return;
+ loadPrivate(&cfg,QString(""),cnt);
+}
+
+void KviNickServRuleSet::save(const QString &szConfigFile)
+{
+ KviConfig cfg(szConfigFile,KviConfig::Write);
+ cfg.clear();
+ save(&cfg,QString(""));
+}
+
+bool KviNickServRuleSet::loadPrivate(KviConfig * cfg,const QString &prefix,unsigned int nEntries)
+{
+ if(m_pRules)m_pRules->clear();
+ else {
+ m_pRules = new KviPointerList<KviNickServRule>;
+ m_pRules->setAutoDelete(true);
+ }
+
+ if(nEntries != 0)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"%QNSEnabled",&prefix);
+ m_bEnabled = cfg->readBoolEntry(tmp,false);
+ for(unsigned int u=0;u<nEntries;u++)
+ {
+ KviQString::sprintf(tmp,"%QNSRule%u_",&prefix,u);
+ KviNickServRule * r = new KviNickServRule();
+ if(!r->load(cfg,tmp))delete r;
+ else m_pRules->append(r);
+ }
+ }
+
+ if(m_pRules->isEmpty())
+ {
+ m_bEnabled = false;
+ delete m_pRules;
+ m_pRules = 0;
+ return false;
+ }
+ return true;
+}
+
+void KviNickServRuleSet::clear()
+{
+ if(m_pRules)
+ {
+ delete m_pRules;
+ m_pRules = 0;
+ }
+ m_bEnabled = false;
+}
+
+void KviNickServRuleSet::addRule(KviNickServRule * r)
+{
+ if(!m_pRules)
+ {
+ m_pRules = new KviPointerList<KviNickServRule>;
+ m_pRules->setAutoDelete(true);
+ }
+ m_pRules->append(r);
+}
+
+KviNickServRuleSet * KviNickServRuleSet::createInstance()
+{
+ return new KviNickServRuleSet();
+}
+
+
+KviNickServRule * KviNickServRuleSet::matchRule(const QString &szNick,const KviIrcMask *nickServ,const QString &szMsg,const QString &szServer)
+{
+ if(!m_pRules)return 0;
+ for(KviNickServRule *r = m_pRules->first();r;r = m_pRules->next())
+ {
+ if(!KviQString::matchStringCI(r->registeredNick(),szNick,false,true)) continue;
+ if(!szServer.isEmpty())
+ {
+#ifdef COMPILE_USE_QT4
+ QRegExp res(r->serverMask(),Qt::CaseInsensitive,QRegExp::Wildcard);
+#else
+ QRegExp res(r->serverMask(),false,true);
+#endif
+ if(!res.exactMatch(szServer))continue;
+ }
+ if(!nickServ->matchedBy(KviIrcMask(r->nickServMask())))continue;
+#ifdef COMPILE_USE_QT4
+ QRegExp re(r->messageRegexp(),Qt::CaseInsensitive,QRegExp::Wildcard);
+#else
+ QRegExp re(r->messageRegexp(),false,true);
+#endif
+ if(re.exactMatch(szMsg))return r;
+ }
+ return 0;
+}
+
+void KviNickServRuleSet::copyFrom(const KviNickServRuleSet &src)
+{
+ if(src.m_pRules)
+ {
+ if(m_pRules)m_pRules->clear();
+ else {
+ m_pRules = new KviPointerList<KviNickServRule>;
+ m_pRules->setAutoDelete(true);
+ }
+ for(KviNickServRule * r = src.m_pRules->first();r;r = src.m_pRules->next())
+ {
+ KviNickServRule * c = new KviNickServRule();
+ c->copyFrom(*r);
+ m_pRules->append(c);
+ }
+ if(m_pRules->isEmpty())
+ {
+ m_bEnabled = false;
+ delete m_pRules;
+ m_pRules = 0;
+ } else {
+ m_bEnabled = src.m_bEnabled;
+ }
+ } else {
+ m_bEnabled = false;
+ if(m_pRules)
+ {
+ delete m_pRules;
+ m_pRules = 0;
+ }
+ }
+}
+
+
+void KviNickServRule::copyFrom(const KviNickServRule &src)
+{
+ m_szRegisteredNick = src.m_szRegisteredNick;
+ m_szNickServMask = src.m_szNickServMask;
+ m_szMessageRegexp = src.m_szMessageRegexp;
+ m_szIdentifyCommand = src.m_szIdentifyCommand;
+ m_szServerMask = src.m_szServerMask;
+}
+
+void KviNickServRule::save(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QRegisteredNick",&prefix);
+ cfg->writeEntry(tmp,m_szRegisteredNick);
+ KviQString::sprintf(tmp,"%QNickServMask",&prefix);
+ cfg->writeEntry(tmp,m_szNickServMask);
+ KviQString::sprintf(tmp,"%QMessageRegexp",&prefix);
+ cfg->writeEntry(tmp,m_szMessageRegexp);
+ KviQString::sprintf(tmp,"%QIdentifyCommand",&prefix);
+ cfg->writeEntry(tmp,m_szIdentifyCommand);
+ KviQString::sprintf(tmp,"%QServerMask",&prefix);
+ cfg->writeEntry(tmp,m_szServerMask);
+}
+
+bool KviNickServRule::load(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QRegisteredNick",&prefix);
+ m_szRegisteredNick = KviQString::trimmed(cfg->readQStringEntry(tmp));
+ if(m_szRegisteredNick.isEmpty())return false;
+ KviQString::sprintf(tmp,"%QNickServMask",&prefix);
+ m_szNickServMask = cfg->readQStringEntry(tmp);
+ if(m_szNickServMask.isEmpty())return false;
+ KviQString::sprintf(tmp,"%QServerMask",&prefix);
+ m_szServerMask = cfg->readQStringEntry(tmp,QString::null);
+ KviQString::sprintf(tmp,"%QMessageRegexp",&prefix);
+ m_szMessageRegexp = cfg->readQStringEntry(tmp);
+ if(m_szMessageRegexp.isEmpty())return false;
+ KviQString::sprintf(tmp,"%QIdentifyCommand",&prefix);
+ m_szIdentifyCommand = cfg->readQStringEntry(tmp);
+ return !m_szIdentifyCommand.isEmpty();
+}
+
+KviNickServRule * KviNickServRule::createInstance(const QString &szRegisteredNick,
+ const QString &szNickServMask,
+ const QString &szMessageRegexp,
+ const QString &szIdentifyCommand,
+ const QString &szServerMask)
+{
+ return new KviNickServRule(szRegisteredNick,szNickServMask,szMessageRegexp,szIdentifyCommand,szServerMask);
+}
+
+
+
+
diff --git a/src/kvilib/irc/kvi_nickserv.h b/src/kvilib/irc/kvi_nickserv.h
new file mode 100644
index 00000000..105eed1c
--- /dev/null
+++ b/src/kvilib/irc/kvi_nickserv.h
@@ -0,0 +1,112 @@
+#ifndef _KVI_NICKSERV_H_
+#define _KVI_NICKSERV_H_
+//=============================================================================
+//
+// File : kvi_nickserv.h
+// Creation date : Thu Aug 09 2001 16:43:56 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_heapobject.h"
+#include "kvi_pointerlist.h"
+
+class KviConfig;
+class KviIrcMask;
+
+class KVILIB_API KviNickServRule : public KviHeapObject
+{
+protected:
+ QString m_szRegisteredNick; // my registered nickname
+ QString m_szNickServMask; // the NickServ service mask
+ QString m_szMessageRegexp; // the NickServ message regexp
+ QString m_szIdentifyCommand; // the IDENTIFY command to send to server
+ QString m_szServerMask; // the mask that the server must match (not used in per-network rules)
+public:
+ KviNickServRule() : KviHeapObject() {};
+ KviNickServRule(
+ const QString &szRegisteredNick,
+ const QString &szNickServMask,
+ const QString &szMessageRegexp,
+ const QString &szIdentifyCommand,
+ const QString &szServerMask = QString::null)
+ : KviHeapObject(),
+ m_szRegisteredNick(szRegisteredNick),
+ m_szNickServMask(szNickServMask),
+ m_szMessageRegexp(szMessageRegexp),
+ m_szIdentifyCommand(szIdentifyCommand),
+ m_szServerMask(szServerMask)
+ {};
+public:
+ const QString & registeredNick() const { return m_szRegisteredNick; };
+ const QString & nickServMask() const { return m_szNickServMask; };
+ const QString & messageRegexp() const { return m_szMessageRegexp; };
+ const QString & identifyCommand() const { return m_szIdentifyCommand; };
+ const QString & serverMask() const { return m_szServerMask; };
+ void setRegisteredNick(const QString &szRegisteredNick){ m_szRegisteredNick = szRegisteredNick; };
+ void setNickServMask(const QString &szNickServMask){ m_szNickServMask = szNickServMask; };
+ void setMessageRegexp(const QString &szMessageRegexp){ m_szMessageRegexp = szMessageRegexp; };
+ void setIdentifyCommand(const QString &szIdentifyCommand){ m_szIdentifyCommand = szIdentifyCommand; };
+ void setServerMask(const QString &szServerMask){ m_szServerMask = szServerMask; };
+public:
+ // avoid crashes under windows
+ static KviNickServRule * createInstance(const QString &szRegisteredNick,
+ const QString &szNickServMask,
+ const QString &szMessageRegexp,
+ const QString &szIdentifyCommand,
+ const QString &szServerMask = QString::null);
+
+ void save(KviConfig * cfg,const QString &prefix);
+ // returns false if the loaded data has no sense
+ bool load(KviConfig * cfg,const QString &prefix);
+ void copyFrom(const KviNickServRule &src);
+};
+
+class KVILIB_API KviNickServRuleSet : public KviHeapObject
+{
+public:
+ KviNickServRuleSet();
+ KviNickServRuleSet(const KviNickServRuleSet &s);
+ ~KviNickServRuleSet();
+protected:
+ KviPointerList<KviNickServRule> * m_pRules; // FIXME: Replace with KviPointerHashTable<QString,KviPointerList>
+ bool m_bEnabled;
+public:
+ // avoid crashes under windows
+ static KviNickServRuleSet * createInstance();
+ void clear();
+ bool isEnabled(){ return m_bEnabled; };
+ void setEnabled(bool bEnabled){ m_bEnabled = bEnabled; };
+ bool isEmpty(){ return m_pRules ? m_pRules->isEmpty() : true; };
+ void addRule(KviNickServRule * r);
+ KviNickServRule * matchRule(const QString &szNick,const KviIrcMask *nickServ,const QString &szMsg,const QString &szServer = QString::null);
+ void copyFrom(const KviNickServRuleSet &src);
+ void load(const QString &szConfigFile);
+ void save(const QString &szConfigFile);
+ void save(KviConfig * cfg,const QString &prefix);
+ KviPointerList<KviNickServRule> * rules(){ return m_pRules; };
+ static KviNickServRuleSet * load(KviConfig * cfg,const QString &prefix);
+protected:
+ bool loadPrivate(KviConfig * cfg,const QString &prefix,unsigned int nEntries);
+};
+
+
+#endif // _KVI_NICKSERV_H_
diff --git a/src/kvilib/irc/kvi_useridentity.cpp b/src/kvilib/irc/kvi_useridentity.cpp
new file mode 100644
index 00000000..d4791333
--- /dev/null
+++ b/src/kvilib/irc/kvi_useridentity.cpp
@@ -0,0 +1,252 @@
+//=============================================================================
+//
+// File : kvi_useridentity.cpp
+// Created on Sun 21 Jan 2007 04:31:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot net>
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_useridentity.h"
+#include "kvi_locale.h"
+#include "kvi_defaults.h"
+
+// FIXME: Put here also the default away message, default away nick, default ctcp replies etc ?
+
+bool KviUserIdentity::load(KviConfig &cfg)
+{
+ m_szId = cfg.group();
+ m_szNickName = cfg.readQStringEntry("NickName");
+ m_szAltNickName1 = cfg.readQStringEntry("AltNickName1");
+ m_szAltNickName2 = cfg.readQStringEntry("AltNickName2");
+ m_szAltNickName3 = cfg.readQStringEntry("AltNickName3");
+ m_szUserName = cfg.readQStringEntry("UserName");
+ // FIXME: At least scramble the pass ?
+ m_szPassword = cfg.readQStringEntry("Password");
+ KviPixmap def;
+ m_pixAvatar = cfg.readPixmapEntry("Avatar",def);
+ m_szPartMessage = cfg.readQStringEntry("PartMessage");
+ m_szQuitMessage= cfg.readQStringEntry("QuitMessage");
+ m_szAge = cfg.readQStringEntry("Age");
+ m_szGender = cfg.readQStringEntry("Gender");
+ m_szLocation = cfg.readQStringEntry("Location");
+ m_szLanguages = cfg.readQStringEntry("Languages");
+ m_szOtherInfo = cfg.readQStringEntry("OtherInfo");
+ m_szUserMode = cfg.readQStringEntry("UserMode");
+ m_szOnConnectCommand = cfg.readQStringEntry("OnConnectCommand");
+ m_szOnLoginCommand = cfg.readQStringEntry("OnLoginCommand");
+ return !(m_szId.isEmpty() || m_szNickName.isEmpty());
+}
+
+bool KviUserIdentity::save(KviConfig &cfg)
+{
+ cfg.setGroup(m_szId);
+ cfg.writeEntry("NickName",m_szNickName);
+ cfg.writeEntry("AltNickName1",m_szAltNickName1);
+ cfg.writeEntry("AltNickName2",m_szAltNickName2);
+ cfg.writeEntry("AltNickName3",m_szAltNickName3);
+ cfg.writeEntry("UserName",m_szUserName);
+ // FIXME: At least scramble the pass ?
+ cfg.writeEntry("Password",m_szPassword);
+ cfg.writeEntry("Avatar",m_pixAvatar);
+ cfg.writeEntry("PartMessage",m_szPartMessage);
+ cfg.writeEntry("QuitMessage",m_szQuitMessage);
+ cfg.writeEntry("Age",m_szAge);
+ cfg.writeEntry("Gender",m_szGender);
+ cfg.writeEntry("Location",m_szLocation);
+ cfg.writeEntry("Languages",m_szLanguages);
+ cfg.writeEntry("OtherInfo",m_szOtherInfo);
+ cfg.writeEntry("UserMode",m_szUserMode);
+ cfg.writeEntry("OnConnectCommand",m_szOnConnectCommand);
+ cfg.writeEntry("OnLoginCommand",m_szOnLoginCommand);
+ return true;
+}
+
+void KviUserIdentity::copyFrom(const KviUserIdentity &src)
+{
+ m_szId = src.m_szId;
+ m_szNickName = src.m_szNickName;
+
+ m_szAltNickName1 = src.m_szAltNickName1;
+ m_szAltNickName2 = src.m_szAltNickName2;
+ m_szAltNickName3 = src.m_szAltNickName3;
+
+ m_szUserName = src.m_szUserName;
+ m_szRealName = src.m_szRealName;
+ m_szPassword = src.m_szPassword;
+
+ m_pixAvatar = src.m_pixAvatar;
+
+ m_szUserName = src.m_szUserName;
+ m_szRealName = src.m_szRealName;
+ m_szPassword = src.m_szPassword;
+
+ m_pixAvatar = src.m_pixAvatar;
+
+ m_szPartMessage = src.m_szPartMessage;
+ m_szQuitMessage = src.m_szQuitMessage;
+
+ m_szAge = src.m_szAge;
+ m_szGender = src.m_szGender;
+ m_szLocation = src.m_szLocation;
+ m_szLanguages = src.m_szLanguages;
+ m_szOtherInfo = src.m_szOtherInfo;
+
+ m_szUserMode = src.m_szUserMode;
+
+ m_szOnConnectCommand = src.m_szOnConnectCommand;
+ m_szOnLoginCommand = src.m_szOnLoginCommand;
+}
+
+
+KviUserIdentityManager * KviUserIdentityManager::m_pInstance = 0;
+
+KviUserIdentityManager::KviUserIdentityManager()
+: KviHeapObject()
+{
+ m_pIdentityDict = new KviPointerHashTable<QString,KviUserIdentity>();
+ m_pIdentityDict->setAutoDelete(true);
+}
+
+KviUserIdentityManager::~KviUserIdentityManager()
+{
+ delete m_pIdentityDict;
+}
+
+void KviUserIdentityManager::init()
+{
+ if(m_pInstance)return;
+ m_pInstance = new KviUserIdentityManager();
+}
+
+void KviUserIdentityManager::done()
+{
+ if(!m_pInstance)return;
+ delete m_pInstance;
+ m_pInstance = 0;
+}
+
+const KviUserIdentity * KviUserIdentityManager::defaultIdentity()
+{
+ KviUserIdentity * ret;
+ if(!m_szDefaultIdentity.isEmpty())
+ {
+ ret = m_pIdentityDict->find(m_szDefaultIdentity);
+ if(ret)return ret;
+ }
+
+ // the default identity is borken :/
+ // grab the first one
+ KviPointerHashTableIterator<QString,KviUserIdentity> it(*m_pIdentityDict);
+ ret = it.current();
+ if(ret)
+ {
+ m_szDefaultIdentity = ret->id();
+ return ret;
+ }
+ // no identities available: create the default
+ ret = new KviUserIdentity();
+
+ ret->setId(__tr2qs("Default"));
+ ret->setNickName(KVI_DEFAULT_NICKNAME1);
+ ret->setAltNickName1(KVI_DEFAULT_NICKNAME2);
+ ret->setAltNickName2(KVI_DEFAULT_NICKNAME3);
+ ret->setAltNickName3(KVI_DEFAULT_NICKNAME4);
+ ret->setUserName(KVI_DEFAULT_USERNAME);
+ ret->setRealName(KVI_DEFAULT_REALNAME);
+ ret->setPartMessage(KVI_DEFAULT_PART_MESSAGE);
+ ret->setQuitMessage(KVI_DEFAULT_QUIT_MESSAGE);
+
+ m_pIdentityDict->replace(ret->id(),ret);
+
+ return ret;
+}
+
+void KviUserIdentityManager::load(const QString &szFileName)
+{
+ m_pIdentityDict->clear();
+
+ KviConfig cfg(szFileName,KviConfig::Read);
+
+ cfg.setGroup("KVIrc");
+
+ m_szDefaultIdentity = cfg.readQStringEntry("DefaultIdentity","");
+
+ KviConfigIterator it(*(cfg.dict()));
+ while(KviConfigGroup * grp = it.current())
+ {
+ if(!KviQString::equalCI(it.currentKey(),"KVIrc"))
+ {
+ cfg.setGroup(it.currentKey());
+
+ KviUserIdentity * id = new KviUserIdentity();
+ if(id->load(cfg))
+ m_pIdentityDict->replace(id->id(),id);
+ else
+ delete id;
+ }
+ ++it;
+ }
+}
+
+void KviUserIdentityManager::save(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+ cfg.clear();
+
+ cfg.setGroup("KVIrc");
+
+ cfg.writeEntry("DefaultIdentity",m_szDefaultIdentity);
+
+ KviPointerHashTableIterator<QString,KviUserIdentity> it(*m_pIdentityDict);
+ while(KviUserIdentity * id = it.current())
+ {
+ id->save(cfg);
+ ++it;
+ }
+}
+
+void KviUserIdentityManager::copyFrom(KviUserIdentityManager * pWorkingCopy)
+{
+ m_pIdentityDict->clear();
+ m_szDefaultIdentity = pWorkingCopy->m_szDefaultIdentity;
+ KviPointerHashTableIterator<QString,KviUserIdentity> it(*(pWorkingCopy->m_pIdentityDict));
+ while(KviUserIdentity * id = it.current())
+ {
+ KviUserIdentity * pNew = new KviUserIdentity();
+ pNew->copyFrom(*id);
+ m_pIdentityDict->replace(pNew->id(),pNew);
+ ++it;
+ }
+}
+
+KviUserIdentityManager * KviUserIdentityManager::createWorkingCopy()
+{
+ KviUserIdentityManager * pCopy = new KviUserIdentityManager();
+ pCopy->copyFrom(this);
+ return pCopy;
+}
+
+void KviUserIdentityManager::releaseWorkingCopy(KviUserIdentityManager * pWorkingCopy)
+{
+ if(pWorkingCopy)delete pWorkingCopy;
+}
+
+
diff --git a/src/kvilib/irc/kvi_useridentity.h b/src/kvilib/irc/kvi_useridentity.h
new file mode 100644
index 00000000..c1018f1a
--- /dev/null
+++ b/src/kvilib/irc/kvi_useridentity.h
@@ -0,0 +1,145 @@
+#ifndef _KVI_USERIDENTITY_H_
+#define _KVI_USERIDENTITY_H_
+//=============================================================================
+//
+// File : kvi_useridentity.h
+// Created on Sun 21 Jan 2007 04:31:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot net>
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_pixmap.h"
+#include "kvi_config.h"
+#include "kvi_pointerhashtable.h"
+
+class KVILIB_API KviUserIdentity : public KviHeapObject
+{
+ friend class KviUserIdentityManager;
+public:
+ KviUserIdentity()
+ : KviHeapObject()
+ {
+ }
+ ~KviUserIdentity()
+ {
+ }
+protected:
+ QString m_szId; // the identity set name
+
+ QString m_szNickName;
+
+ QString m_szAltNickName1;
+ QString m_szAltNickName2;
+ QString m_szAltNickName3;
+
+ QString m_szUserName;
+ QString m_szRealName;
+ QString m_szPassword;
+
+ KviPixmap m_pixAvatar;
+
+ QString m_szPartMessage;
+ QString m_szQuitMessage;
+
+ QString m_szAge;
+ QString m_szGender;
+ QString m_szLocation;
+ QString m_szLanguages;
+ QString m_szOtherInfo;
+
+ QString m_szUserMode;
+
+ QString m_szOnConnectCommand;
+ QString m_szOnLoginCommand;
+public:
+ const QString & id() const { return m_szId; };
+ const QString & nickName() const { return m_szNickName; };
+ const QString & altNickName1() const { return m_szAltNickName1; };
+ const QString & altNickName2() const { return m_szAltNickName2; };
+ const QString & altNickName3() const { return m_szAltNickName3; };
+ const QString & userName() const { return m_szUserName; };
+ const QString & password() const { return m_szPassword; };
+ const KviPixmap & avatar() const { return m_pixAvatar; };
+ const QString & partMessage() const { return m_szPartMessage; };
+ const QString & quitMessage() const { return m_szQuitMessage; };
+ const QString & age() const { return m_szAge; };
+ const QString & gender() const { return m_szGender; };
+ const QString & location() const { return m_szLocation; };
+ const QString & languages() const { return m_szLanguages; };
+ const QString & otherInfo() const { return m_szOtherInfo; };
+ const QString & userMode() const { return m_szUserMode; };
+ const QString & onConnectCommand() const { return m_szOnConnectCommand; };
+ const QString & onLoginCommand() const { return m_szOnLoginCommand; };
+ void setId(const QString &szId){ m_szId = szId; };
+ void setNickName(const QString &szNickName){ m_szNickName = szNickName; };
+ void setAltNickName1(const QString &szNickName){ m_szAltNickName1 = szNickName; };
+ void setAltNickName2(const QString &szNickName){ m_szAltNickName2 = szNickName; };
+ void setAltNickName3(const QString &szNickName){ m_szAltNickName3 = szNickName; };
+ void setUserName(const QString &szUserName){ m_szUserName = szUserName; };
+ void setRealName(const QString &szRealName){ m_szRealName = szRealName; };
+ void setPassword(const QString &szPassword){ m_szPassword = szPassword; };
+ void setAvatar(const KviPixmap &pix){ m_pixAvatar = pix; };
+ void setPartMessage(const QString &szMsg){ m_szPartMessage = szMsg; };
+ void setQuitMessage(const QString &szMsg){ m_szQuitMessage = szMsg; };
+ void setAge(const QString &szAge){ m_szAge = szAge; };
+ void setGender(const QString &szGender){ m_szGender = szGender; };
+ void setLocation(const QString &szLocation){ m_szLocation = szLocation; };
+ void setLanguages(const QString &szLanguages){ m_szLanguages = szLanguages; };
+ void setOtherInfo(const QString &szOtherInfo){ m_szOtherInfo = szOtherInfo; };
+ void setUserMode(const QString &szUserMode){ m_szUserMode = szUserMode; };
+ void setOnConnectCommand(const QString &szOnConnectCommand){ m_szOnConnectCommand = szOnConnectCommand; };
+ void setOnLoginCommand(const QString &szOnLoginCommand){ m_szOnLoginCommand = szOnLoginCommand; };
+protected:
+ void copyFrom(const KviUserIdentity &src);
+ bool save(KviConfig &cfg);
+ bool load(KviConfig &cfg);
+};
+
+class KVILIB_API KviUserIdentityManager : public KviHeapObject
+{
+protected:
+ KviUserIdentityManager();
+ ~KviUserIdentityManager();
+protected:
+ static KviUserIdentityManager * m_pInstance;
+ KviPointerHashTable<QString,KviUserIdentity> * m_pIdentityDict;
+ QString m_szDefaultIdentity;
+public:
+ static void init();
+ static void done();
+ static KviUserIdentityManager * instance(){ return m_pInstance; };
+
+ KviPointerHashTable<QString,KviUserIdentity> * identityDict(){ return m_pIdentityDict; };
+ const KviUserIdentity * findIdentity(const QString &szId){ return m_pIdentityDict->find(szId); };
+ // NEVER NULL
+ const KviUserIdentity * defaultIdentity();
+
+ void setDefaultIdentity(const QString &szIdentityId){ m_szDefaultIdentity = szIdentityId; };
+
+ KviUserIdentityManager * createWorkingCopy();
+ void copyFrom(KviUserIdentityManager * pWorkingCopy);
+ void releaseWorkingCopy(KviUserIdentityManager * pWorkingCopy);
+
+ void save(const QString &szFileName);
+ void load(const QString &szFileName);
+};
+
+#endif //!_KVI_USERIDENTITY_H_
diff --git a/src/kvilib/irc/moc_kvi_ircuserdb.cpp b/src/kvilib/irc/moc_kvi_ircuserdb.cpp
new file mode 100644
index 00000000..2b4d1482
--- /dev/null
+++ b/src/kvilib/irc/moc_kvi_ircuserdb.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+** KviIrcUserDataBase meta object code from reading C++ file 'kvi_ircuserdb.h'
+**
+** Created: Sun Mar 23 20:56:18 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_ircuserdb.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviIrcUserDataBase::className() const
+{
+ return "KviIrcUserDataBase";
+}
+
+QMetaObject *KviIrcUserDataBase::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcUserDataBase( "KviIrcUserDataBase", &KviIrcUserDataBase::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcUserDataBase::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcUserDataBase", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcUserDataBase::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcUserDataBase", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcUserDataBase::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_slot_0[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod slot_0 = {"registeredUserRemoved", 1, param_slot_0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"registeredUserChanged", 1, param_slot_1 };
+ static const QUParameter param_slot_2[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod slot_2 = {"registeredUserAdded", 1, param_slot_2 };
+ static const QUMethod slot_3 = {"registeredDatabaseCleared", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "registeredUserRemoved(const QString&)", &slot_0, QMetaData::Protected },
+ { "registeredUserChanged(const QString&)", &slot_1, QMetaData::Protected },
+ { "registeredUserAdded(const QString&)", &slot_2, QMetaData::Protected },
+ { "registeredDatabaseCleared()", &slot_3, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcUserDataBase", parentObject,
+ slot_tbl, 4,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcUserDataBase.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcUserDataBase::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcUserDataBase" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviIrcUserDataBase::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: registeredUserRemoved((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 1: registeredUserChanged((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 2: registeredUserAdded((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 3: registeredDatabaseCleared(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcUserDataBase::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcUserDataBase::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviIrcUserDataBase::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES