diff --git a/AuthManager.lua b/AuthManager.lua
new file mode 100644
index 0000000..37931c6
--- /dev/null
+++ b/AuthManager.lua
@@ -0,0 +1,117 @@
+--[[
+ * Copyright (c) 2011-2012 by Adam Hellberg.
+ *
+ * This file is part of Command.
+ *
+ * Command 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Command 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 Command. If not, see <http://www.gnu.org/licenses/>.
+--]]
+
+-- Upvalues
+local tostring = tostring
+local tonumber = tonumber
+local math = math
+
+local C = Command
+
+C.AuthManager = {
+ Users = {}
+}
+
+local AM = C.AuthManager
+local CES = C.Extensions.String
+local CET = C.Extensions.Table
+
+local function GeneratePassword(user, pass)
+ local pass = ("%s:%s"):format(tostring(user):upper(), tostring(pass))
+ -- TODO: Make generation better
+ return pass
+end
+
+local function Verify(user, pass)
+ user = tostring(user):upper()
+ if not AM.Users[user] then return false end
+ if not AM.Users[user].Enabled then return false end
+ if AM.Users[user].Authed then return true end
+ if not pass:match("^%w+:%w+$") then
+ pass = ("%s:%s"):format(user, pass)
+ end
+ local uPass = tostring(AM.Users[user].Pass)
+ local split = CES:Split(pass, ":")
+ local u = tostring(split[1])
+ local p = tostring(split[2])
+ pass = ("%s:%s"):format(u:upper(), p)
+ return pass == uPass
+end
+
+function AM:Authenticate(user, pass)
+ user = tostring(user):upper()
+ if not self.Users[user] then
+ return false, "AM_ERR_NOEXISTS", {user}
+ elseif not self.Users[user].Enabled then
+ return false, "AM_ERR_DISABLED", {user}
+ elseif self.Users[user].Authed then
+ return false, "AM_ERR_AUTHED", {user}
+ end
+ if Verify(user, pass) then
+ self.Users[user].Authed = true
+ return "AM_AUTH_SUCCESS", {user, self.Users[user].Level}
+ end
+ self.Users[user].Authed = false
+ return false, "AM_AUTH_ERR_INVALIDPASS"
+end
+
+function AM:Add(user, level, pass, notify)
+ user = tostring(user):upper()
+ level = tonumber(level)
+ if self.Users[user] then
+ return false, "AM_ERR_USEREXISTS", {user}
+ elseif not level then
+ return false, "AM_ERR_NOLEVEL"
+ end
+ pass = pass or tostring(math.random(123, 9999)) -- Lame default password
+ pass = GeneratePassword(user, pass)
+ local userTable = {
+ Name = user,
+ Pass = pass,
+ Enabled = true,
+ Authed = false,
+ Level = level
+ }
+ self.Users[user] = CET:Copy(userTable)
+ if notify then
+ C.ChatManager:SendMessage(C.LocaleManager("AM_ADD_WHISPER"):format(level, pass), "WHISPER", user)
+ end
+ return "AM_ADD_SUCCESS", {user, level, pass}
+end
+
+function AM:Remove(user)
+ user = tostring(user):upper()
+ if not self.Users[user] then return false, "AM_ERR_NOEXISTS", {user} end
+ self.Users[user] = nil
+ return "AM_REMOVE_SUCCESS", {user}
+end
+
+function AM:Enable(user)
+ user = tostring(user):upper()
+ if not self.Users[user] then return false, "AM_ERR_NOEXISTS", {user} end
+ self.Users[user].Enabled = true
+ return "AM_ENABLE_SUCCESS", {user}
+end
+
+function AM:Disable(user)
+ user = tostring(user):upper()
+ if not self.Users[user] then return false, "AM_ERR_NOEXISTS", {user} end
+ self.Users[user].Enabled = false
+ return "AM_DISABLE_SUCCESS", {user}
+end
diff --git a/ChatManager.lua b/ChatManager.lua
index f95cb85..740bf74 100644
--- a/ChatManager.lua
+++ b/ChatManager.lua
@@ -108,7 +108,10 @@ end
function CM:SendMessage(msg, channel, target, isBN)
isBN = isBN or false
if not self.Settings.LOCAL_ONLY then
- msg = ("[%s] %s"):format(C.Name, tostring(msg))
+ -- Sanitize message
+ --msg = msg:gsub("|*", "|") -- First make sure every pipe char is alone (This is probably not needed)
+ msg = tostring(msg):gsub("|", "||") -- Escape the pipe characters
+ msg = ("[%s] %s"):format(C.Name, msg)
if channel == "SMART" then
if GT:IsRaid() then
channel = "RAID"
@@ -170,9 +173,11 @@ end
--- Handle a chat message.
-- @param msg The message to handle.
-- @param sender Player object of the player who sent the message.
--- @param channel Channel the message was sent from.
+-- @param channel The channel to which HandleMessage will send the result.
-- @param target Player or channel index.
+-- @param sourceChannel The source channel that the message was sent from.
-- @param isBN True if battle.net message, false or nil otherwise.
+-- @param pID Player ID (for battle.net messages, this is nil when isBN is false or nil).
--
function CM:HandleMessage(msg, sender, channel, target, sourceChannel, isBN, pID)
isBN = isBN or false
@@ -220,6 +225,10 @@ function CM:HandleMessage(msg, sender, channel, target, sourceChannel, isBN, pID
end
end
elseif result == "RAW_TABLE_OUTPUT" then
+ if type(arg) ~= "table" then
+ error("Received RAW_TABLE_OUTPUT request, but arg was of type '" .. type(arg) .. "', expected 'table', aborting...")
+ return
+ end
for _,v in ipairs(arg) do
self:SendMessage(tostring(v), channel, target, isBN)
end
diff --git a/CommandManager.lua b/CommandManager.lua
index 69e578a..92b3886 100644
--- a/CommandManager.lua
+++ b/CommandManager.lua
@@ -49,6 +49,7 @@ local QM = C.QueueManager
local RM = C.RollManager
local LM = C.LootManager
local GT = C.GroupTools
+local AM = C.AuthManager
local Chat
local CES = C.Extensions.String
local CET = C.Extensions.Table
@@ -372,6 +373,38 @@ CM:Register({"ban"}, PM.Access.Groups.Admin.Level, function(args, sender, isChat
return PM:BanUser(player)
end, "CM_BAN_HELP")
+CM:Register({"auth", "authenticate", "a"}, PM.Access.Local, function(args, sender, isChat)
+ if isChat and isChat ~= "WHISPER" then return false, "CM_ERR_NOCHAT" end
+ if #args < 2 then return false, "CM_AUTH_USAGE" end
+ local arg = tostring(args[1]):lower()
+ local target = tostring(args[2]):upper()
+ local notify = true
+ if target == UnitName("player"):upper() then return false, "CM_AUTH_ERR_SELF" end
+ if sender.Info.Name:upper() == target then notify = false end
+ if arg:match("^a") then -- Add
+ local level = tonumber(args[3])
+ local pass = args[4]
+ if not level then
+ return false, "CM_AUTH_ADDUSAGE"
+ end
+ return AM:Add(target, level, pass, notify)
+ elseif arg:match("^r") then -- Remove
+ return AM:Remove(target)
+ elseif arg:match("^e") then -- Enable
+ return AM:Enable(target)
+ elseif arg:match("^d") then -- Disable
+ return AM:Disable(target)
+ end
+ return false, "CM_AUTH_USAGE"
+end, "CM_AUTH_HELP")
+
+CM:Register({"authme", "authenticateme", "am"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
+ if not isChat then return false, "CM_ERR_CHATONLY" end
+ if #args <= 0 then return false, "CM_AUTHME_USAGE" end
+ local pass = tostring(args[1])
+ return AM:Authenticate(sender.Info.Name, pass)
+end, "CM_AUTHME_HELP")
+
CM:Register({"accept", "acceptinvite", "acceptinv", "join", "joingroup"}, PM.Access.Groups.User.Level, function(args, sender, isChat)
if not StaticPopup_Visible("PARTY_INVITE") then
return false, "CM_ACCEPTINVITE_NOTACTIVE"
diff --git a/PlayerManager.lua b/PlayerManager.lua
index e2ef7ae..d27c4c8 100644
--- a/PlayerManager.lua
+++ b/PlayerManager.lua
@@ -1,18 +1,18 @@
--[[
* Copyright (c) 2011-2012 by Adam Hellberg.
- *
+ *
* This file is part of Command.
- *
+ *
* Command 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 3 of the License, or
* (at your option) any later version.
- *
+ *
* Command 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 Command. If not, see <http://www.gnu.org/licenses/>.
--]]
@@ -32,6 +32,7 @@ local C = Command
local L = C.LocaleManager
local CM
local GT = C.GroupTools
+local AM = C.AuthManager
local BNT = C.BattleNetTools
local CCM
local CET = C.Extensions.Table
@@ -45,6 +46,9 @@ local log
--
C.PlayerManager = {
VarVersion = 1,
+ Dialogs = {
+ Kick = "COMMAND_CONFIRMKICK"
+ },
Access = {
Min = 0,
Max = 4,
@@ -145,7 +149,7 @@ local function KickCancelled(name, sender)
CM:SendMessage(msg, CM.LastChannel, CM.LastTarget)
end
-StaticPopupDialogs["COMMAND_CONFIRMKICK"] = {
+StaticPopupDialogs[PM.Dialogs.Kick] = {
text = "PM_KICK_POPUP",
button1 = "YES",
button2 = "NO",
@@ -218,7 +222,7 @@ end
-- @return Player from list of players if exists, otherwise a new player object.
--
function PM:GetOrCreatePlayer(name)
- name = name:lower():gsub("^%l", string.upper)
+ name = (name or UnitName("player")):lower():gsub("^%l", string.upper)
if CET:HasKey(Players, name) then
return Players[name]
else
@@ -455,12 +459,19 @@ function PM:HasAccess(player, command)
return true
end
local hasAccess = self:GetAccess(player) <= command.Access
+ local auth = AM.Users[player.Info.Name:upper()]
+ if auth then
+ local authLevel = tonumber(auth.Level)
+ if authLevel and auth.Enabled and auth.Authed then
+ if authLevel <= command.Access then hasAccess = true end
+ end
+ end
local group = self.Access.Groups[player.Info.Group]
if CET:HasValue(group.Allow, command.Name) then hasAccess = true end
if CET:HasValue(group.Deny, command.Name) then hasAccess = false end
if CET:HasValue(player.Access.Allow, command.Name) then hasAccess = true end
if CET:HasValue(player.Access.Deny, command.Name) then hasAccess = false end
- if (List[command.Name] and self:GetListMode() == MODE_BLACKLIST) or (not List[command.Name] and self:GetListMode() == MODE_WHITELIST) then
+ if not self:IsCommandAllowed(command) then
hasAccess = false
end
return hasAccess
@@ -641,10 +652,10 @@ function PM:Kick(player, sender, reason, override)
KickName = player.Info.Name
KickSender = sender.Info.Name
KickReason = reason or L("PM_KICK_DEFAULTREASON"):format(KickSender)
- StaticPopupDialogs.COMMAND_CONFIRMKICK.text = L("PM_KICK_POPUP")
- StaticPopupDialogs.COMMAND_CONFIRMKICK.button1 = L("YES")
- StaticPopupDialogs.COMMAND_CONFIRMKICK.button2 = L("NO")
- StaticPopup_Show("COMMAND_CONFIRMKICK", KickSender, KickName)
+ StaticPopupDialogs[self.Dialogs.Kick].text = L("PM_KICK_POPUP")
+ StaticPopupDialogs[self.Dialogs.Kick].button1 = L("YES")
+ StaticPopupDialogs[self.Dialogs.Kick].button2 = L("NO")
+ StaticPopup_Show(self.Dialogs.Kick, KickSender, KickName)
return "PM_KICK_WAIT", {KickName}
end
return false, "PM_KICK_NOPRIV", {player.Info.Name}
diff --git a/load.xml b/load.xml
index d1498bf..0c197c8 100644
--- a/load.xml
+++ b/load.xml
@@ -1,18 +1,18 @@
<!--
* Copyright (c) 2011-2012 by Adam Hellberg.
- *
+ *
* This file is part of Command.
- *
+ *
* Command 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 3 of the License, or
* (at your option) any later version.
- *
+ *
* Command 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 Command. If not, see <http://www.gnu.org/licenses/>.
-->
@@ -26,6 +26,7 @@
<Script file="Logger.lua" />
<Script file="BattleNetTools.lua" />
<Script file="GroupTools.lua" />
+ <Script file="AuthManager.lua" />
<Script file="PlayerManager.lua" />
<Script file="QueueManager.lua" />
<Script file="RollManager.lua" />
diff --git a/locales/enUS.lua b/locales/enUS.lua
index cadd148..fc6553f 100644
--- a/locales/enUS.lua
+++ b/locales/enUS.lua
@@ -134,6 +134,14 @@ local L = {
CM_BAN_HELP = "Ban a player.",
CM_BAN_USAGE = "Usage: ban <name>",
+ CM_AUTH_HELP = "Add/Remove/Enable/Disable auths.",
+ CM_AUTH_USAGE = "Usage: auth add|remove|enable|disable <target>",
+ CM_AUTH_ADDUSAGE = "Usage: auth add <target> <level> [password]",
+ CM_AUTH_ERR_SELF = "Cannot modify myself in auth list.",
+
+ CM_AUTHME_HELP = "Authenticates the sender if the correct pass is specified.",
+ CM_AUTHME_USAGE = "Usage: authme <password>",
+
CM_ACCEPTINVITE_HELP = "Accepts a pending group invite.",
CM_ACCEPTINVITE_NOTACTIVE = "No pending invites active.",
CM_ACCEPTINVITE_EXISTS = "I am already in a group.",
@@ -404,6 +412,28 @@ local L = {
PM_LIST_SETWHITE = "Now using list as whitelist.",
PM_LIST_SETBLACK = "Now using list as blacklist.",
+ -----------------
+ -- AuthManager --
+ -----------------
+
+ AM_ERR_NOEXISTS = "%q does not exist in the auth list.",
+ AM_ERR_USEREXISTS = "%q is already in the auth list, please authenticate with authme.",
+ AM_ERR_DISABLED = "%q is disabled in the auth list.",
+ AM_ERR_NOLEVEL = "No access level specified.",
+ AM_ERR_AUTHED = "%q is already authenticated!",
+
+ AM_AUTH_ERR_INVALIDPASS = "Invalid password.",
+ AM_AUTH_SUCCESS = "%q successfully authenticated for access level %d!",
+
+ AM_ADD_SUCCESS = "Added %q to auth list for access level %d, password: %s. Authenticate with !authme.",
+ AM_ADD_WHISPER = "Added you to the auth list for access level %d, password: %s. Authenticate with !authme.",
+
+ AM_REMOVE_SUCCESS = "Removed %q from auth list.",
+
+ AM_ENABLE_SUCCESS = "Enabled %q for authentication.",
+
+ AM_DISABLE_SUCCESS = "Disabled %q from authenticating.",
+
----------------
-- GroupTools --
----------------
diff --git a/locales/svSE.lua b/locales/svSE.lua
index daee112..fe63925 100644
--- a/locales/svSE.lua
+++ b/locales/svSE.lua
@@ -134,6 +134,14 @@ local L = {
CM_BAN_HELP = "Bannlys en användare.",
CM_BAN_USAGE = "Användning: ban <namn>",
+ CM_AUTH_HELP = "Add/Remove/Enable/Disable auths.",
+ CM_AUTH_USAGE = "Användning: auth add|remove|enable|disable <target>",
+ CM_AUTH_ADDUSAGE = "Användning: auth add <target> <level> [password]",
+ CM_AUTH_ERR_SELF = "Cannot modify myself in auth list.",
+
+ CM_AUTHME_HELP = "Authenticates the sender if the correct pass is specified.",
+ CM_AUTHME_USAGE = "Användning: authme <password>",
+
CM_ACCEPTINVITE_HELP = "Accepterar en pågående gruppinbjudan.",
CM_ACCEPTINVITE_NOTACTIVE = "Inga aktiva inbjudningar just nu.",
CM_ACCEPTINVITE_EXISTS = "Jag är redan i en grupp.",
@@ -404,6 +412,28 @@ local L = {
PM_LIST_SETWHITE = "Now using list as whitelist.",
PM_LIST_SETBLACK = "Now using list as blacklist.",
+ -----------------
+ -- AuthManager --
+ -----------------
+
+ AM_ERR_NOEXISTS = "%q does not exist in the auth list.",
+ AM_ERR_USEREXISTS = "%q is already in the auth list, please authenticate with authme.",
+ AM_ERR_DISABLED = "%q is disabled in the auth list.",
+ AM_ERR_NOLEVEL = "No access level specified.",
+ AM_ERR_AUTHED = "%q is already authenticated!",
+
+ AM_AUTH_ERR_INVALIDPASS = "Invalid password.",
+ AM_AUTH_SUCCESS = "%q successfully authenticated for access level %d!",
+
+ AM_ADD_SUCCESS = "Added %q to auth list for access level %d, password: %s. Authenticate with !authme.",
+ AM_ADD_WHISPER = "Added you to the auth list for access level %d, password: %s. Authenticate with !authme.",
+
+ AM_REMOVE_SUCCESS = "Removed %q from auth list.",
+
+ AM_ENABLE_SUCCESS = "Enabled %q for authentication.",
+
+ AM_DISABLE_SUCCESS = "Disabled %q from authenticating.",
+
----------------
-- GroupTools --
----------------