diff options
Diffstat (limited to 'src/kvilib/irc')
-rw-r--r-- | src/kvilib/irc/Makefile.am | 5 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_avatar.cpp | 165 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_avatar.h | 83 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_avatarcache.cpp | 250 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_avatarcache.h | 69 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_ircmask.cpp | 760 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_ircmask.h | 164 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_ircserver.cpp | 373 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_ircserver.h | 206 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_ircserverdb.cpp | 646 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_ircserverdb.h | 116 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_ircuserdb.cpp | 285 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_ircuserdb.h | 145 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_mirccntrl.cpp | 307 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_mirccntrl.h | 163 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_nickserv.cpp | 312 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_nickserv.h | 112 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_useridentity.cpp | 252 | ||||
-rw-r--r-- | src/kvilib/irc/kvi_useridentity.h | 145 | ||||
-rw-r--r-- | src/kvilib/irc/moc_kvi_ircuserdb.cpp | 119 |
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 |