Added functionality for dynamic modes using ISUPPORT (raw 005)

git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@278 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
prozacx
2005-05-13 23:22:55 +00:00
parent 081234b724
commit 93e5b8575b
7 changed files with 399 additions and 165 deletions
+161 -89
View File
@@ -2,6 +2,7 @@
#include "znc.h"
#include "User.h"
#include "Utils.h"
#include "IRCSock.h"
CChan::CChan(const CString& sName, CUser* pUser) {
m_sName = sName.Token(0);
@@ -12,6 +13,7 @@ CChan::CChan(const CString& sName, CUser* pUser) {
}
m_pUser = pUser;
m_Nick.SetUser(pUser);
m_bAutoCycle = true;
m_bDetached = false;
m_uBufferCount = m_pUser->GetBufferCount();
@@ -25,11 +27,8 @@ CChan::~CChan() {
void CChan::Reset() {
m_bWhoDone = false;
m_bIsOn = false;
m_bIsOp = false;
m_bIsVoice = false;
m_uOpCount = 0;
m_uVoiceCount = 0;
m_uModes = 0;
m_suUserPerms.clear();
m_musModes.clear();
m_uLimit = 0;
m_uClientRequests = 0;
m_sTopic = "";
@@ -63,10 +62,9 @@ void CChan::JoinUser(bool bForce) {
CString sLine = sPre;
for (map<CString,CNick*>::iterator a = m_msNicks.begin(); a != m_msNicks.end(); a++) {
if (a->second->IsOp()) {
sLine += "@";
} else if (a->second->IsVoice()) {
sLine += "+";
char c = a->second->GetPermChar();
if (c != '\0') {
sLine += c;
}
sLine += a->first;
@@ -110,23 +108,21 @@ void CChan::DetachUser() {
m_bDetached = true;
}
CString CChan::GetModeCString() const {
CString sRet;
CString CChan::GetModeString() const {
CString sModes, sArgs;
if (m_uModes & Secret) { sRet += "s"; }
if (m_uModes & Private) { sRet += "p"; }
if (m_uModes & OpTopic) { sRet += "t"; }
if (m_uModes & InviteOnly) { sRet += "i"; }
if (m_uModes & NoMessages) { sRet += "n"; }
if (m_uModes & Moderated) { sRet += "m"; }
if (m_uLimit) { sRet += "l"; }
if (m_uModes & Key) { sRet += "k"; }
for (map<unsigned char, CString>::const_iterator it = m_musModes.begin(); it != m_musModes.end(); it++) {
sModes += it->first;
if (it->second.size()) {
sArgs += " " + it->second;
}
}
return (sRet.empty()) ? sRet : ("+" + sRet);
return (sModes.empty()) ? sModes : ("+" + sModes + sArgs);
}
void CChan::SetModes(const CString& sModes) {
m_uModes = 0;
m_musModes.clear();
m_uLimit = 0;
m_sKey = "";
ModeChange(sModes);
@@ -176,26 +172,96 @@ void CChan::ModeChange(const CString& sModes, const CString& sOpNick) {
#endif
for (unsigned int a = 0; a < sModeArg.size(); a++) {
switch (sModeArg[a]) {
case '+': bAdd = true; break;
case '-': bAdd = false; break;
case 's': if (bAdd) { m_uModes |= Secret; } else { m_uModes &= ~Secret; } break;
case 'p': if (bAdd) { m_uModes |= Private; } else { m_uModes &= ~Private; } break;
case 'm': if (bAdd) { m_uModes |= Moderated; } else { m_uModes &= ~Moderated; } break;
case 'i': if (bAdd) { m_uModes |= InviteOnly; } else { m_uModes &= ~InviteOnly; } break;
case 'n': if (bAdd) { m_uModes |= NoMessages; } else { m_uModes &= ~NoMessages; } break;
case 't': if (bAdd) { m_uModes |= OpTopic; } else { m_uModes &= ~OpTopic; } break;
case 'l': if (bAdd) { m_uLimit = strtoul(GetModeArg(sArgs).c_str(), NULL, 10); } else { m_uLimit = 0; } break;
case 'k': if (bAdd) { m_uModes |= Key; SetKey(GetModeArg(sArgs)); } else { m_uModes &= ~Key; GetModeArg(sArgs); } break;
case 'o': OnOp(sOpNick, GetModeArg(sArgs), bAdd); break;
case 'v': OnVoice(sOpNick, GetModeArg(sArgs), bAdd); break;
case 'b': // Don't do anything with bans yet
case 'e': // Don't do anything with excepts yet
default: GetModeArg(sArgs); // Pop off an arg, assume new modes will have an argument
const unsigned char& uMode = sModeArg[a];
CString sArg;
if (uMode == '+') {
bAdd = true;
} else if (uMode == '-') {
bAdd = false;
} else if (m_pUser->GetIRCSock()->IsPermMode(uMode)) {
sArg = GetModeArg(sArgs);
CNick* pNick = FindNick(sArg);
if (pNick) {
unsigned char uPerm = m_pUser->GetIRCSock()->GetPermFromMode(uMode);
if (uPerm) {
if (bAdd) {
if (pNick->AddPerm(uPerm)) {
IncPermCount(uPerm);
}
if (pNick->GetNick().CaseCmp(m_pUser->GetCurNick()) == 0) {
AddPerm(uPerm);
}
} else {
if (pNick->RemPerm(uPerm)) {
DecPermCount(uPerm);
}
if (pNick->GetNick().CaseCmp(m_pUser->GetCurNick()) == 0) {
RemPerm(uPerm);
}
}
}
}
} else {
switch (m_pUser->GetIRCSock()->GetModeType(uMode)) {
case CIRCSock::ListArg:
sArg = GetModeArg(sArgs);
break;
case CIRCSock::HasArg:
sArg = GetModeArg(sArgs);
break;
case CIRCSock::NoArg:
break;
case CIRCSock::ArgWhenSet:
if (bAdd) {
sArg = GetModeArg(sArgs);
}
break;
}
(bAdd) ? AddMode(uMode, sArg) : RemMode(uMode, sArg);
}
}
}
CString CChan::GetModeArg(unsigned char uMode) const {
if (uMode) {
map<unsigned char, CString>::const_iterator it = m_musModes.find(uMode);
if (it != m_musModes.end()) {
return it->second;
}
}
return "";
}
bool CChan::HasMode(unsigned char uMode) const {
return (uMode && m_musModes.find(uMode) != m_musModes.end());
}
bool CChan::AddMode(unsigned char uMode, const CString& sArg) {
if (HasMode(uMode)) {
return false;
}
m_musModes[uMode] = sArg;
return true;
}
bool CChan::RemMode(unsigned char uMode, const CString& sArg) {
if (!HasMode(uMode)) {
return false;
}
m_musModes.erase(uMode);
return true;
}
CString CChan::GetModeArg(CString& sArgs) const {
CString sRet = sArgs.substr(0, sArgs.find(' '));
sArgs = (sRet.size() < sArgs.size()) ? sArgs.substr(sRet.size() +1) : "";
@@ -245,53 +311,28 @@ int CChan::AddNicks(const CString& sNicks) {
bool CChan::AddNick(const CString& sNick) {
const char* p = sNick.c_str();
bool bIsOp = false;
bool bIsVoice = false;
bool bNoMode = false;
char cPrefix = '\0';
switch (*p) {
case '\0':
if (m_pUser->GetIRCSock()->IsPermChar(*p)) {
cPrefix = *p;
if (!*++p) {
return false;
case '@':
bIsOp = true;
break;
case '+':
bIsVoice = true;
break;
case '%':
break;
case '*':
break;
case '!':
break;
default:
bNoMode = true;
break;
}
if (!bNoMode && !*++p) {
return false;
}
}
CNick* pNick = FindNick(p);
if (!pNick) {
pNick = new CNick(p);
pNick->SetUser(m_pUser);
}
if ((bIsOp) && (!pNick->IsOp())) {
IncOpCount();
pNick->SetOp(true);
if (pNick->AddPerm(cPrefix)) {
IncPermCount(cPrefix);
}
if (pNick->GetNick().CaseCmp(m_pUser->GetCurNick()) == 0) {
SetOpped(true);
}
} else if ((bIsVoice) && (!pNick->IsVoice())) {
IncVoiceCount();
pNick->SetVoice(true);
if (pNick->GetNick().CaseCmp(m_pUser->GetCurNick()) == 0) {
SetVoiced(true);
}
if (pNick->GetNick().CaseCmp(m_pUser->GetCurNick()) == 0) {
AddPerm(cPrefix);
}
m_msNicks[pNick->GetNick()] = pNick;
@@ -299,25 +340,50 @@ bool CChan::AddNick(const CString& sNick) {
return true;
}
unsigned int CChan::GetPermCount(unsigned char uPerm) {
map<unsigned char, unsigned int>::iterator it = m_muuPermCount.find(uPerm);
return (it == m_muuPermCount.end()) ? 0 : it->second;
}
void CChan::DecPermCount(unsigned char uPerm) {
map<unsigned char, unsigned int>::iterator it = m_muuPermCount.find(uPerm);
if (it == m_muuPermCount.end()) {
m_muuPermCount[uPerm] = 0;
} else {
if (it->second) {
m_muuPermCount[uPerm]--;
}
}
}
void CChan::IncPermCount(unsigned char uPerm) {
map<unsigned char, unsigned int>::iterator it = m_muuPermCount.find(uPerm);
if (it == m_muuPermCount.end()) {
m_muuPermCount[uPerm] = 1;
} else {
m_muuPermCount[uPerm]++;
}
}
bool CChan::RemNick(const CString& sNick) {
map<CString,CNick*>::iterator it = m_msNicks.find(sNick);
if (it == m_msNicks.end()) {
return false;
}
if (it->second->IsOp()) {
DecOpCount();
}
const set<unsigned char>& suPerms = it->second->GetChanPerms();
if (it->second->IsVoice()) {
DecVoiceCount();
for (set<unsigned char>::iterator it = suPerms.begin(); it != suPerms.end(); it++) {
DecPermCount(*it);
}
delete it->second;
m_msNicks.erase(it);
CNick* pNick = m_msNicks.begin()->second;
if ((m_msNicks.size() == 1) && (!pNick->IsOp()) && (pNick->GetNick().CaseCmp(m_pUser->GetCurNick()) == 0)) {
if ((m_msNicks.size() == 1) && (!pNick->HasPerm(Op)) && (pNick->GetNick().CaseCmp(m_pUser->GetCurNick()) == 0)) {
if (AutoCycle()) {
Cycle();
}
@@ -336,7 +402,7 @@ bool CChan::ChangeNick(const CString& sOldNick, const CString& sNewNick) {
// Rename this nick
it->second->SetNick(sNewNick);
// Insert a new element into the map then erase the old one, do this to change the key
// Insert a new element into the map then erase the old one, do this to change the key to the new nick
m_msNicks[sNewNick] = it->second;
m_msNicks.erase(it);
@@ -347,7 +413,7 @@ void CChan::OnOp(const CString& sOpNick, const CString& sNick, bool bOpped) {
CNick* pNick = FindNick(sNick);
if (pNick) {
bool bNoChange = (pNick->IsOp() == bOpped);
bool bNoChange = (pNick->HasPerm(Op) == bOpped);
#ifdef _MODULES
CNick* pOpNick = FindNick(sOpNick);
@@ -361,7 +427,7 @@ void CChan::OnOp(const CString& sOpNick, const CString& sNick, bool bOpped) {
#endif
if (sNick.CaseCmp(m_pUser->GetCurNick()) == 0) {
SetOpped(bOpped);
(bOpped) ? AddPerm(Op) : RemPerm(Op);
}
if (bNoChange) {
@@ -369,8 +435,11 @@ void CChan::OnOp(const CString& sOpNick, const CString& sNick, bool bOpped) {
return;
}
pNick->SetOp(bOpped);
(bOpped) ? IncOpCount() : DecOpCount();
bool bChange = (bOpped) ? pNick->AddPerm(Op) : pNick->RemPerm(Op);
if (bChange) {
(bOpped) ? IncPermCount(Op) : DecPermCount(Op);
}
}
}
@@ -378,7 +447,7 @@ void CChan::OnVoice(const CString& sOpNick, const CString& sNick, bool bVoiced)
CNick* pNick = FindNick(sNick);
if (pNick) {
bool bNoChange = (pNick->IsVoice() == bVoiced);
bool bNoChange = (pNick->HasPerm(Voice) == bVoiced);
#ifdef _MODULES
CNick* pOpNick = FindNick(sOpNick);
@@ -393,7 +462,7 @@ void CChan::OnVoice(const CString& sOpNick, const CString& sNick, bool bVoiced)
#endif
if (sNick.CaseCmp(m_pUser->GetCurNick()) == 0) {
SetVoiced(bVoiced);
(bVoiced) ? AddPerm(Voice) : RemPerm(Voice);
}
if (bNoChange) {
@@ -401,8 +470,11 @@ void CChan::OnVoice(const CString& sOpNick, const CString& sNick, bool bVoiced)
return;
}
pNick->SetVoice(bVoiced);
(bVoiced) ? IncVoiceCount() : DecVoiceCount();
bool bChange = (bVoiced) ? pNick->AddPerm(Voice) : pNick->RemPerm(Voice);
if (bChange) {
(bVoiced) ? IncPermCount(Voice) : DecPermCount(Voice);
}
}
}
+45 -26
View File
@@ -2,10 +2,13 @@
#define _CHAN_H
#include "Nick.h"
#include "String.h"
#include <vector>
#include <map>
#include <set>
using std::vector;
using std::map;
using std::set;
// Forward Declarations
class CUser;
@@ -14,14 +17,27 @@ class CUser;
class CChan {
public:
typedef enum {
Private = 1 << 0,
Secret = 1 << 1,
NoMessages = 1 << 2,
Moderated = 1 << 3,
OpTopic = 1 << 4,
InviteOnly = 1 << 5,
Key = 1 << 6
} EMode;
Voice = '+',
HalfOp = '%',
Op = '@',
Admin = '!',
Owner = '*'
} EUserPerms;
typedef enum {
M_Private = 'p',
M_Secret = 's',
M_Moderated = 'm',
M_InviteOnly = 'i',
M_NoMessages = 'n',
M_OpTopic = 't',
M_Limit = 'l',
M_Key = 'k',
M_Op = 'o',
M_Voice = 'v',
M_Ban = 'b',
M_Except = 'e',
} EModes;
CChan(const CString& sName, CUser* pUser);
virtual ~CChan();
@@ -42,9 +58,11 @@ public:
// Modes
void SetModes(const CString& s);
void ModeChange(const CString& sModes, const CString& sNick = "");
bool AddMode(unsigned char uMode, const CString& sArg);
bool RemMode(unsigned char uMode, const CString& sArg);
void OnOp(const CString& sOpNick, const CString& sNick, bool bOpped);
void OnVoice(const CString& sOpNick, const CString& sNick, bool bVoiced);
CString GetModeCString() const;
CString GetModeString() const;
CString GetModeArg(CString& sArgs) const;
// !Modes
@@ -62,19 +80,22 @@ public:
void ClearBuffer();
// !Buffer
// m_Nick wrappers
CString GetPermStr() const { return m_Nick.GetPermStr(); }
bool HasPerm(unsigned char uPerm) const { return m_Nick.HasPerm(uPerm); }
bool AddPerm(unsigned char uPerm) { return m_Nick.AddPerm(uPerm); }
bool RemPerm(unsigned char uPerm) { return m_Nick.RemPerm(uPerm); }
// !wrappers
// Setters
void IncPermCount(unsigned char uPerm);
void DecPermCount(unsigned char uPerm);
void SetIsOn(bool b) { m_bIsOn = b; if (!b) { Reset(); } else { Joined(); } }
void SetOpped(bool b) { m_bIsOp = b; }
void SetVoiced(bool b) { m_bIsVoice = b; }
void SetKey(const CString& s) { m_sKey = s; }
void SetTopic(const CString& s) { m_sTopic = s; }
void SetTopicOwner(const CString& s) { m_sTopicOwner = s; }
void SetTopicDate(unsigned long u) { m_ulTopicDate = u; }
void SetDefaultModes(const CString& s) { m_sDefaultModes = s; }
void IncOpCount() { m_uOpCount++; }
void DecOpCount() { m_uOpCount -= (m_uOpCount > 0); }
void IncVoiceCount() { m_uVoiceCount++; }
void DecVoiceCount() { m_uVoiceCount -= (m_uVoiceCount > 0); }
void SetBufferCount(unsigned int u) { m_uBufferCount = u; }
void SetKeepBuffer(bool b) { m_bKeepBuffer = b; }
void SetAutoCycle(bool b) { m_bAutoCycle = b; }
@@ -83,11 +104,12 @@ public:
// !Setters
// Getters
bool HasMode(unsigned char uMode) const;
CString GetModeArg(unsigned char uMode) const;
unsigned int GetPermCount(unsigned char uPerm);
const bool IsOn() const { return m_bIsOn; }
const bool IsOp() const { return m_bIsOp; }
const bool IsVoice() const { return m_bIsVoice; }
const CString& GetName() const { return m_sName; }
unsigned int GetModes() const { return m_uModes; }
const map<unsigned char, CString>& GetModes() const { return m_musModes; }
const CString& GetKey() const { return m_sKey; }
unsigned int GetLimit() const { return m_uLimit; }
const CString& GetTopic() const { return m_sTopic; }
@@ -98,10 +120,7 @@ public:
const vector<CString>& GetBuffer() const { return m_vsBuffer; }
const map<CString,CNick*>& GetNicks() const { return m_msNicks; }
unsigned int GetNickCount() const { return m_msNicks.size(); }
unsigned int GetOpCount() const { return m_uOpCount; }
unsigned int GetVoiceCount() const { return m_uVoiceCount; }
unsigned int GetBufferCount() const { return m_uBufferCount; }
bool HasMode(EMode eMode) const { return (m_uModes & eMode); }
bool KeepBuffer() const { return m_bKeepBuffer; }
bool AutoCycle() const { return m_bAutoCycle; }
bool IsDetached() const { return m_bDetached; }
@@ -110,8 +129,6 @@ private:
protected:
bool m_bDetached;
bool m_bIsOn;
bool m_bIsOp;
bool m_bIsVoice;
bool m_bWhoDone;
bool m_bKeepBuffer;
bool m_bAutoCycle;
@@ -121,16 +138,18 @@ protected:
CString m_sTopicOwner;
unsigned long m_ulTopicDate;
CUser* m_pUser;
CNick m_Nick;
unsigned int m_uLimit;
unsigned int m_uModes;
CString m_sDefaultModes;
vector<CString> m_vsBans;
map<CString,CNick*> m_msNicks; // Todo: make this caseless (irc style)
set<unsigned int> m_suUserPerms;
unsigned int m_uBufferCount;
unsigned int m_uOpCount;
unsigned int m_uVoiceCount;
unsigned int m_uClientRequests; // Used to tell how many times a client tried to join this chan
vector<CString> m_vsBuffer;
map<unsigned char, CString> m_musModes;
map<unsigned char, unsigned int> m_muuPermCount;
};
#endif // !_CHAN_H
+51 -3
View File
@@ -17,7 +17,17 @@ CIRCSock::CIRCSock(CZNC* pZNC, CUser* pUser) : Csock() {
m_MotdBuffer.SetLineCount(200); // This should be more than enough motd lines
m_Nick.SetIdent(pUser->GetIdent());
m_Nick.SetHost(pUser->GetVHost());
m_sNickPrefixes = "+@";
m_sPerms = "@+";
m_sPermModes = "ov";
m_mueChanModes['p'] = NoArg;
m_mueChanModes['s'] = NoArg;
m_mueChanModes['t'] = NoArg;
m_mueChanModes['i'] = NoArg;
m_mueChanModes['n'] = NoArg;
m_mueChanModes['b'] = HasArg;
m_mueChanModes['e'] = HasArg;
m_mueChanModes['k'] = HasArg;
m_mueChanModes['l'] = ArgWhenSet;
}
CIRCSock::~CIRCSock() {
@@ -873,12 +883,50 @@ void CIRCSock::ParseISupport(const CString& sLine) {
if (sName.CaseCmp("PREFIX") == 0) {
CString sPrefixes = sValue.Token(1, false, ')');
CString sPermModes = sValue.Token(0, false, ')');
sPermModes.LeftTrim("(");
if (!sPrefixes.empty()) {
m_sNickPrefixes = sPrefixes;
if (!sPrefixes.empty() && sPermModes.size() == sPrefixes.size()) {
m_sPerms = sPrefixes;
m_sPermModes = sPermModes;
}
} else if (sName.CaseCmp("CHANMODES") == 0) {
if (!sValue.empty()) {
m_mueChanModes.clear();
for (unsigned int a = 0; a < 4; a++) {
CString sModes = sValue.Token(a, false, ',');
for (unsigned int b = 0; b < sModes.size(); b++) {
m_mueChanModes[sModes[b]] = (EChanModeArgs) a;
}
}
}
}
sArg = sLine.Token(i++);
}
}
unsigned char CIRCSock::GetPermFromMode(unsigned char uMode) const {
if (m_sPermModes.size() == m_sPerms.size()) {
for (unsigned int a = 0; a < m_sPermModes.size(); a++) {
if (m_sPermModes[a] == uMode) {
return m_sPerms[a];
}
}
}
return 0;
}
CIRCSock::EChanModeArgs CIRCSock::GetModeType(unsigned char uMode) const {
map<unsigned char, EChanModeArgs>::const_iterator it = m_mueChanModes.find(uMode);
if (it == m_mueChanModes.end()) {
return NoArg;
}
return it->second;
}
+31 -16
View File
@@ -16,6 +16,13 @@ public:
CIRCSock(CZNC* pZNC, CUser* pUser);
virtual ~CIRCSock();
typedef enum {
ListArg = 0, // These values must line up with their position in the CHANMODE argument to raw 005
HasArg = 1,
ArgWhenSet = 2,
NoArg = 3
} EChanModeArgs;
// Message Handlers
bool OnCTCPReply(const CString& sNickMask, CString& sMessage);
bool OnPrivCTCP(const CString& sNickMask, CString& sMessage);
@@ -47,29 +54,37 @@ public:
// !Setters
// Getters
CString GetNickMask() const {
return m_Nick.GetNickMask();
}
EChanModeArgs GetModeType(unsigned char uMode) const;
unsigned char GetPermFromMode(unsigned char uMode) const;
const map<unsigned char, EChanModeArgs>& GetChanModes() const { return m_mueChanModes; }
bool IsPermChar(const char c) const { return (c != '\0' && GetPerms().find(c) != CString::npos); }
bool IsPermMode(const char c) const { return (c != '\0' && GetPermModes().find(c) != CString::npos); }
const CString& GetPerms() const { return m_sPerms; }
const CString& GetPermModes() const { return m_sPermModes; }
CString GetNickMask() const { return m_Nick.GetNickMask(); }
const CString& GetNick() const { return m_Nick.GetNick(); }
const CString& GetPass() const { return m_sPass; }
// !Getters
private:
void SetNick(const CString& sNick);
protected:
bool m_bISpoofReleased;
bool m_bAuthed;
bool m_bKeepNick;
CString m_sNickPrefixes;
CZNC* m_pZNC;
CUser* m_pUser;
CNick m_Nick;
CString m_sPass;
CBuffer m_RawBuffer;
CBuffer m_MotdBuffer;
CUserSock* m_pUserSock;
bool m_bISpoofReleased;
bool m_bAuthed;
bool m_bKeepNick;
CString m_sPerms;
CString m_sPermModes;
map<unsigned char, EChanModeArgs> m_mueChanModes;
CZNC* m_pZNC;
CUser* m_pUser;
CNick m_Nick;
CString m_sPass;
CBuffer m_RawBuffer;
CBuffer m_MotdBuffer;
CUserSock* m_pUserSock;
map<CString, CChan*> m_msChans;
unsigned int m_uQueryBufferCount;
CBuffer m_QueryBuffer;
unsigned int m_uQueryBufferCount;
CBuffer m_QueryBuffer;
};
#endif // !_IRCSOCK_H
+60 -9
View File
@@ -1,20 +1,23 @@
#include "Nick.h"
#include "Chan.h"
#include "Nick.h"
#include "User.h"
#include "IRCSock.h"
CNick::CNick() {
m_bIsOp = false;
m_bIsVoice = false;
Reset();
}
CNick::CNick(const CString& sNick) {
Reset();
Parse(sNick);
m_bIsOp = false;
m_bIsVoice = false;
}
CNick::~CNick() {}
void CNick::Reset() {
m_cPerm = '\0';
}
void CNick::Parse(const CString& sNickMask) {
if (sNickMask.empty()) {
return;
@@ -56,14 +59,62 @@ unsigned int CNick::GetCommonChans(vector<CChan*>& vRetChans, CUser* pUser) cons
return vRetChans.size();
}
void CNick::SetUser(CUser* pUser) { m_pUser = pUser; }
void CNick::SetPermChar(char c) { m_cPerm = c; }
void CNick::SetNick(const CString& s) { m_sNick = s; }
void CNick::SetIdent(const CString& s) { m_sIdent = s; }
void CNick::SetHost(const CString& s) { m_sHost = s; }
void CNick::SetOp(bool b) { m_bIsOp = b; }
void CNick::SetVoice(bool b) { m_bIsVoice = b; }
bool CNick::IsOp() const { return m_bIsOp; }
bool CNick::IsVoice() const { return m_bIsVoice; }
bool CNick::HasPerm(unsigned char uPerm) const {
return (uPerm && m_suChanPerms.find(uPerm) != m_suChanPerms.end());
}
bool CNick::AddPerm(unsigned char uPerm) {
if (!uPerm || HasPerm(uPerm)) {
return false;
}
m_suChanPerms.insert(uPerm);
UpdatePermChar();
return true;
}
bool CNick::RemPerm(unsigned char uPerm) {
if (!HasPerm(uPerm)) {
return false;
}
m_suChanPerms.erase(uPerm);
UpdatePermChar();
return true;
}
void CNick::UpdatePermChar() {
const CString& sChanPerms = (!m_pUser) ? "@+" : m_pUser->GetIRCSock()->GetPerms();
m_cPerm = 0;
for (unsigned int a = 0; a < sChanPerms.size(); a++) {
const unsigned char& c = sChanPerms[a];
if (HasPerm(c)) {
m_cPerm = c;
break;
}
}
}
const set<unsigned char>& CNick::GetChanPerms() const { return m_suChanPerms; }
const unsigned char CNick::GetPermChar() const { return m_cPerm; }
CString CNick::GetPermStr() const {
CString sRet;
if (m_cPerm) {
sRet += m_cPerm;
}
return sRet;
}
const CString& CNick::GetNick() const { return m_sNick; }
const CString& CNick::GetIdent() const { return m_sIdent; }
const CString& CNick::GetHost() const { return m_sHost; }
+19 -12
View File
@@ -1,9 +1,11 @@
#ifndef _NICK_H
#define _NICK_H
#include <vector>
#include "String.h"
#include <vector>
#include <set>
using std::vector;
using std::set;
// Forward Decl
class CUser;
@@ -17,21 +19,27 @@ public:
CNick(const CString& sNick);
virtual ~CNick();
void Reset();
void Parse(const CString& sNickMask);
CString GetHostMask() const;
unsigned int GetCommonChans(vector<CChan*>& vChans, CUser* pUser) const;
// Setters
void SetUser(CUser* pUser);
void UpdatePermChar();
void SetPermChar(char c);
void SetNick(const CString& s);
void SetIdent(const CString& s);
void SetHost(const CString& s);
void SetOp(bool b);
void SetVoice(bool b);
bool AddPerm(unsigned char uPerm);
bool RemPerm(unsigned char uPerm);
// !Setters
// Getters
bool IsOp() const;
bool IsVoice() const;
const set<unsigned char>& GetChanPerms() const;
CString GetPermStr() const;
const unsigned char GetPermChar() const;
bool HasPerm(unsigned char uPerm) const;
const CString& GetNick() const;
const CString& GetIdent() const;
const CString& GetHost() const;
@@ -39,13 +47,12 @@ public:
// !Getters
private:
protected:
CString m_sNick;
CString m_sIdent;
CString m_sHost;
bool m_bIsOp;
bool m_bIsVoice;
set<unsigned char> m_suChanPerms;
unsigned char m_cPerm;
CUser* m_pUser;
CString m_sNick;
CString m_sIdent;
CString m_sHost;
};
#endif // !_NICK_H
+32 -10
View File
@@ -408,6 +408,7 @@ void CUserSock::UserCommand(const CString& sLine) {
}
const map<CString,CNick*>& msNicks = pChan->GetNicks();
const CString& sPerms = m_pUser->GetIRCSock()->GetPerms();
if (!msNicks.size()) {
PutStatus("No nicks on [" + sChan + "]");
@@ -415,16 +416,28 @@ void CUserSock::UserCommand(const CString& sLine) {
}
CTable Table;
Table.AddColumn("@");
Table.AddColumn("+");
for (unsigned int p = 0; p < sPerms.size(); p++) {
CString sPerm;
sPerm += sPerms[p];
Table.AddColumn(sPerm);
}
Table.AddColumn("Nick");
Table.AddColumn("Ident");
Table.AddColumn("Host");
for (map<CString,CNick*>::const_iterator a = msNicks.begin(); a != msNicks.end(); a++) {
Table.AddRow();
if (a->second->IsOp()) { Table.SetCell("@", "@"); }
if (a->second->IsVoice()) { Table.SetCell("+", "+"); }
for (unsigned int b = 0; b < sPerms.size(); b++) {
if (a->second->HasPerm(sPerms[b])) {
CString sPerm;
sPerm += sPerms[b];
Table.SetCell(sPerm, sPerm);
}
}
Table.SetCell("Nick", a->second->GetNick());
Table.SetCell("Ident", a->second->GetIdent());
Table.SetCell("Host", a->second->GetHost());
@@ -475,6 +488,7 @@ void CUserSock::UserCommand(const CString& sLine) {
} else if (sCommand.CaseCmp("LISTCHANS") == 0) {
if (m_pUser) {
const vector<CChan*>& vChans = m_pUser->GetChans();
const CString& sPerms = m_pUser->GetIRCSock()->GetPerms();
CTable Table;
Table.AddColumn("Name");
@@ -482,17 +496,21 @@ void CUserSock::UserCommand(const CString& sLine) {
Table.AddColumn("Buf");
Table.AddColumn("Modes");
Table.AddColumn("Users");
Table.AddColumn("+o");
Table.AddColumn("+v");
for (unsigned int p = 0; p < sPerms.size(); p++) {
CString sPerm;
sPerm += sPerms[p];
Table.AddColumn(sPerm);
}
for (unsigned int a = 0; a < vChans.size(); a++) {
CChan* pChan = vChans[a];
Table.AddRow();
Table.SetCell("Name", CString((pChan->IsOp()) ? "@" : ((pChan->IsVoice()) ? "+" : "")) + pChan->GetName());
Table.SetCell("Name", pChan->GetPermStr() + pChan->GetName());
Table.SetCell("Status", ((vChans[a]->IsOn()) ? ((vChans[a]->IsDetached()) ? "Detached" : "Joined") : "Trying"));
Table.SetCell("Buf", CString((pChan->KeepBuffer()) ? "*" : "") + CString::ToString(pChan->GetBufferCount()));
CString sModes = pChan->GetModeCString();
CString sModes = pChan->GetModeString();
unsigned int uLimit = pChan->GetLimit();
const CString& sKey = pChan->GetKey();
@@ -501,8 +519,12 @@ void CUserSock::UserCommand(const CString& sLine) {
Table.SetCell("Modes", sModes);
Table.SetCell("Users", CString::ToString(pChan->GetNickCount()));
Table.SetCell("+o", CString::ToString(pChan->GetOpCount()));
Table.SetCell("+v", CString::ToString(pChan->GetVoiceCount()));
for (unsigned int b = 0; b < sPerms.size(); b++) {
CString sPerm;
sPerm += sPerms[b];
Table.SetCell(sPerm, CString::ToString(pChan->GetPermCount(sPerms[b])));
}
}
if (Table.size()) {