Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 63 additions & 73 deletions script/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,37 @@ function propagateIgnoreList(con, laction, lcharacter)
end
end

-- Checks to see if a kick/ban/timeout is possible
-- returns nil (no errors) if able to kick/ban, otherwise returns error
-- Syntax: canChannelKickBan <connection> <target name> <target handle> <channel handle>
function canChannelKickBan(con, targetname, targetcon, chan)
-- Source connection must be a channel op or above.
if c.isMod(chan, con) ~= true then
return const.FERR_NOT_OP
end

-- Prefer online connection to name if possible.
local target = targetname
if targetcon ~= nil then
target = targetcon
end

if c.isBanned(chan, target) == true then
return const.FERR_ALREADY_CHANNEL_BANNED
end

-- Channel owners or above cannot kick/ban/timeout other owners or above.
if c.isOwner(chan, con) and c.isOwner(chan, target) then
return const.FERR_DENIED_ON_OP
end

if c.isOnlyMod(chan, con) and c.isOnlyMod(chan, target) then
return const.FERR_DENIED_ON_OP
end

return nil
end

-- Bans a person by their account.
-- Syntax: ACB <character>
event.ACB =
Expand Down Expand Up @@ -200,7 +231,7 @@ function (con, args)
end

-- Bans a user from a channel.
-- Syntax:: CKU <channel> <character>
-- Syntax:: CBU <channel> <character>
event.CBU =
function (con, args)
if args.channel == nil or args.character == nil then
Expand All @@ -212,41 +243,24 @@ function (con, args)
return const.FERR_CHANNEL_NOT_FOUND
end

if c.isMod(chan, con) ~= true then
return const.FERR_NOT_OP
end
local targetname = string.lower(args.character)
local targetonline, target = u.getConnection(lowertargetname)

if c.inChannel(chan, con) ~= true then
return const.FERR_USER_NOT_IN_CHANNEL
local canban = canChannelKickBan(con, targetname, target, chan)
if canban ~= nil then
return canban
end

local targetonline, char = u.getConnection(string.lower(args.character))
local chantype = c.getType(chan)
if chantype == "public" then
if targetonline == true and c.isMod(chan, char) == true then
return const.FERR_DENIED_ON_OP
end
s.logAction(con, "CBU", args)
elseif chantype == "private" then
c.removeInvite(chan, string.lower(args.character))
c.removeInvite(chan, targetname)
end

if targetonline == false then
char = args.character
if c.isBanned(chan, string.lower(char)) == true then
return const.FERR_ALREADY_CHANNEL_BANNED
end
c.sendAll(chan, "CBU", {channel=args.channel, operator=u.getName(con), character=char})
c.ban(chan, con, string.lower(char))
else
if c.isBanned(chan, char) == true then
return const.FERR_ALREADY_CHANNEL_BANNED
end
c.sendAll(chan, "CBU", {channel=args.channel, operator=u.getName(con), character=u.getName(char)})
c.ban(chan, con, char)
if c.inChannel(chan, char) == true then
partChannel(chan, char)
end
c.ban(chan, con, targetname)
c.sendAll(chan, "CBU", {channel=args.channel, operator=u.getName(con), character=args.character})
if targetonline and c.inChannel(chan, target) then
partChannel(chan, target)
end

return const.FERR_OK
Expand Down Expand Up @@ -355,31 +369,24 @@ function (con, args)
return const.FERR_CHANNEL_NOT_FOUND
end

local fchar, char = u.getConnection(string.lower(args.character))
if fchar ~= true then
return const.FERR_USER_NOT_FOUND
end

if c.isMod(chan, con) ~= true then
return const.FERR_NOT_OP
end
local targetname = string.lower(args.character)
local targetonline, target = u.getConnection(targetname)

if (c.inChannel(chan, con) ~= true) or (c.inChannel(chan, char) ~= true) then
return const.FERR_USER_NOT_IN_CHANNEL
local cankick = canChannelKickban(con, targetname, target, chan)
if cankick ~= nil then
return cankick
end

local chantype = c.getType(chan)
if chantype == "public" then
if c.isMod(chan, char) == true then
return const.FERR_DENIED_ON_OP
end
s.logAction(con, "CKU", args)
s.logAction(con, "CBU", args)
elseif chantype == "private" then
c.removeInvite(chan, string.lower(args.character))
c.removeInvite(chan, targetname)
end

c.sendAll(chan, "CKU", {channel=args.channel, operator=u.getName(con), character=u.getName(char)})
partChannel(chan, char)
c.sendAll(chan, "CKU", {channel=args.channel, operator=u.getName(con), character=args.character})
if targetonline and c.inChannel(chan, target) then
partChannel(chan, target)
end
return const.FERR_OK
end

Expand Down Expand Up @@ -578,41 +585,24 @@ function (con, args)
return const.FERR_CHANNEL_NOT_FOUND
end

if c.isMod(chan, con) ~= true then
return const.FERR_NOT_OP
end
local targetname = string.lower(args.character)
local targetonline, target = u.getConnection(lowertargetname)

if c.inChannel(chan, con) ~= true then
return const.FERR_USER_NOT_IN_CHANNEL
local cantimeout = canChannelKickban(con, targetname, target, chan)
if cantimeout ~= nil then
return cantimeout
end

local targetonline, char = u.getConnection(string.lower(args.character))
local chantype = c.getType(chan)
if chantype == "public" then
if c.isMod(chan, char) == true then
return const.FERR_DENIED_ON_OP
end
s.logAction(con, "CTU", args)
elseif chantype == "private" then
c.removeInvite(chan, string.lower(args.character))
c.removeInvite(chan, targetname)
end

if targetonline == false then
char = args.character
if c.isBanned(chan, string.lower(char)) == true then
return const.FERR_ALREADY_CHANNEL_BANNED
end
c.sendAll(chan, "CTU", {channel=args.channel, operator=u.getName(con), character=char, length=tonumber(args.length)})
c.timeout(chan, con, string.lower(char), length)
else
if c.isBanned(chan, char) == true then
return const.FERR_ALREADY_CHANNEL_BANNED
end
c.sendAll(chan, "CTU", {channel=args.channel, operator=u.getName(con), character=u.getName(char), length=tonumber(args.length)})
c.timeout(chan, con, char, length)
if c.inChannel(chan, char) == true then
partChannel(chan, char)
end
c.sendAll(chan, "CTU", {channel=args.channel, operator=u.getName(con), character=args.character, length=tonumber(args.length)})
c.timeout(chan, con, targetname, length)
if targetonline and c.inChannel(chan, target) then
partChannel(chan, target)
end

return const.FERR_OK
Expand Down
63 changes: 27 additions & 36 deletions src/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,20 +164,12 @@ bool Channel::inChannel(ConnectionPtr con) {
}

bool Channel::isBanned(ConnectionPtr con) {
chbanmap_t::const_iterator itr = bans.find(con->characterNameLower);
if (itr != bans.end()) {
BanRecord b = itr->second;
if (b.timeout == 0 || b.timeout >= time(0)) {
return true;
} else {
bans.erase(con->characterNameLower);
}
}

return false;
// no reason to rewrite the function: just pass it through
// to the other overload
return isBanned(con->characterNameLower);
}

bool Channel::isBanned(string& name) {
bool Channel::isBanned(const string& name) {
chbanmap_t::const_iterator itr = bans.find(name);
if (itr != bans.end()) {
BanRecord b = itr->second;
Expand All @@ -192,18 +184,10 @@ bool Channel::isBanned(string& name) {
}

bool Channel::getBan(ConnectionPtr con, BanRecord& ban) {
chbanmap_t::const_iterator itr = bans.find(con->characterNameLower);
if (itr != bans.end()) {
BanRecord tmp = itr->second;
ban.banner = tmp.banner;
ban.time = tmp.time;
ban.timeout = tmp.timeout;
return true;
}
return false;
return getBan(con->characterNameLower, ban);
}

bool Channel::getBan(string& name, BanRecord& ban) {
bool Channel::getBan(const string& name, BanRecord& ban) {
chbanmap_t::const_iterator itr = bans.find(name);
if (itr != bans.end()) {
BanRecord tmp = itr->second;
Expand Down Expand Up @@ -233,32 +217,39 @@ void Channel::remMod(string& dest) {
moderators.erase(dest);
}

bool Channel::isMod(ConnectionPtr con) {
if (con->globalModerator || con->admin || (owner == con->characterName) || moderators.find(con->characterName) != moderators.end())
return true;

return false;
bool Channel::isMod(ConnectionPtr con) const {
return con->globalModerator || con->admin || isOnlyOwner(con->characterName) || isOnlyMod(con->characterName);
}

bool Channel::isMod(string& name) {
bool Channel::isMod(const string& name) const {
if ((owner == name) || moderators.find(name) != moderators.end())
return true;

return false;
}

bool Channel::isOwner(ConnectionPtr con) {
if (con->globalModerator || con->admin || (owner == con->characterName))
return true;
bool Channel::isOnlyMod(ConnectionPtr con) const {
return isOnlyMod(con->characterName);
}

return false;
bool Channel::isOnlyMod(const string& name) const {
return moderators.find(name) != moderators.end();
}

bool Channel::isOwner(string& name) {
if (owner == name)
return true;
bool Channel::isOwner(ConnectionPtr con) const {
return con->globalModerator || con->admin || isOwner(con->characterName);
}

return false;
bool Channel::isOwner(const string& name) const {
return owner == name;
}

bool Channel::isOnlyOwner(ConnectionPtr con) const {
return isOnlyOwner(con->characterName);
}

bool Channel::isOnlyOwner(const string& name) const {
return owner == name;
}

const double Channel::getTimerEntry(ConnectionPtr con) {
Expand Down
20 changes: 12 additions & 8 deletions src/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ class Channel : public LBase {
void timeout(ConnectionPtr src, string dest, long length);
void unban(string& dest);
bool isBanned(ConnectionPtr con);
bool isBanned(string& name);
bool isBanned(const string& name);
bool getBan(ConnectionPtr con, BanRecord& ban);
bool getBan(string& name, BanRecord& ban);
bool getBan(const string& name, BanRecord& ban);

const chbanmap_t& getBanRecords() const {
return bans;
Expand All @@ -107,15 +107,19 @@ class Channel : public LBase {
const chmodmap_t& getModRecords() const {
return moderators;
}
bool isMod(ConnectionPtr con);
bool isMod(string& name);

bool isMod(ConnectionPtr con) const;
bool isMod(const string& name) const;
bool isOnlyMod(ConnectionPtr con) const;
bool isOnlyMod(const string& name) const;

const string& getOwner() const {
return owner;
}
bool isOwner(ConnectionPtr con);
bool isOwner(string& name);

bool isOwner(ConnectionPtr con) const;
bool isOwner(const string& name) const;
bool isOnlyOwner(ConnectionPtr con) const;
bool isOnlyOwner(const string& name) const;

void setOwner(string& name) {
owner = name;
}
Expand Down
54 changes: 54 additions & 0 deletions src/lua_channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,60 @@ int LuaChannel::isMod(lua_State* L) {
return 1;
}

/**
* Returns a boolean that describes if a connection or name is a moderator in the channel.
* @param LUD channel
* @param LUD/string connection/name
* @returns true if the connection or name is in the channels moderator list, false otherwise.
*/
int LuaChannel::isOnlyMod(lua_State* L) {
bool ret = false;
luaL_checkany(L, 2);

LBase* base = 0;
GETLCHAN(base, L, 1, chan);
int type = lua_type(L, 2);
if (type == LUA_TLIGHTUSERDATA) {
GETLCON(base, L, 2, con);
ret = chan->isOnlyMod(con);
} else if (type == LUA_TSTRING) {
string name = lua_tostring(L, 2);
ret = chan->isOnlyMod(name);
} else
return luaL_error(L, "isOnlyMod expects string or ConnectionPtr as argument 2.");

lua_pop(L, 2);
lua_pushboolean(L, ret);
return 1;
}

/**
* Returns a boolean that describes if a connection or name is a moderator in the channel.
* @param LUD channel
* @param LUD/string connection/name
* @returns true if the connection or name is an owner, false otherwise
*/
int LuaChannel::isOnlyOwner(lua_State* L) {
bool ret = false;
luaL_checkany(L, 2);

LBase* base = 0;
GETLCHAN(base, L, 1, chan);
int type = lua_type(L, 2);
if (type == LUA_TLIGHTUSERDATA) {
GETLCON(base, L, 2, con);
ret = chan->isOnlyOwner(con);
} else if (type == LUA_TSTRING) {
string name = lua_tostring(L, 2);
ret = chan->isOnlyOwner(name);
} else
return luaL_error(L, "isOnlyOwner expects string or ConnectionPtr as argument 2.");

lua_pop(L, 2);
lua_pushboolean(L, ret);
return 1;
}

/**
* Returns a boolean that describes if a connection or name is the channel owner.
* @param LUD channel
Expand Down
Loading