mirror of
https://github.com/znc/znc.git
synced 2026-05-08 14:24:45 +02:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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()) {
|
||||
|
||||
Reference in New Issue
Block a user