summaryrefslogtreecommitdiff
path: root/network.lua
diff options
context:
space:
mode:
authorTest_User <hax@andrewyu.org>2022-06-12 12:42:18 -0400
committerTest_User <hax@andrewyu.org>2022-06-12 12:42:18 -0400
commit60335b238ad75bbea7e088d16e1717556dbb182a (patch)
tree83e15f1a1231d82768c5ce99d2abaebb33aa9fa2 /network.lua
parent1b60aa9b97c9aea9aa842da3f8dea8816721ad3d (diff)
downloadcoupserv-60335b238ad75bbea7e088d16e1717556dbb182a.tar.gz
coupserv-60335b238ad75bbea7e088d16e1717556dbb182a.zip
nukes
Diffstat (limited to 'network.lua')
-rw-r--r--network.lua175
1 files changed, 175 insertions, 0 deletions
diff --git a/network.lua b/network.lua
new file mode 100644
index 0000000..fbeb168
--- /dev/null
+++ b/network.lua
@@ -0,0 +1,175 @@
+--[[
+
+Network protocol file for HaxServ.
+
+Written by: Test_User <hax@andrewyu.org>
+
+This is free and unencumbered software released into the public
+domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+]]
+
+local function parse_modes(modes, args, has_args, current)
+ local dir = "-"
+ for i = 1, #modes do
+ local mode = modes:sub(i, i)
+
+ if mode == "+" or mode == "-" then
+ dir = mode
+ elseif has_args[mode] and has_args[mode][dir] then
+ if not args[1] then return false end
+
+ if dir == "+" then
+ current[mode] = (type(current[mode]) == "table" and current[mode] or {})
+ current[mode][args[1]] = true
+ else
+ if current[mode] then
+ current[mode][args[1]] = nil
+ end
+ end
+ table.remove(args, 1)
+ else
+ current[mode] = (dir == "+" and true or nil)
+ end
+ end
+ return true
+end
+
+message_handler = {
+ ["PING"] = function(con, source, args, original)
+ con:send(":"..args[2].." PONG "..args[2].." "..source.."\n")
+ end,
+
+ ["SERVER"] = function(con, source, args, original)
+ if source then
+ servlist[args[4]] = {address = args[1], distance = args[3] + 1 + servlist[source].distance, name = args[5], metadata = {}}
+ else
+ servlist[args[4]] = {address = args[1], distance = args[3], name = args[5], metadata = {}}
+ end
+ end,
+
+ ["METADATA"] = function(con, source, args, original)
+ if args[1] == "*" then
+ if servlist[source] then
+ servlist[source].metadata[args[2]] = args[3]
+ else
+ print("Got metadata command from an unknown server!\n")
+ end
+ elseif args[1]:sub(1, 1) == "#" then
+ print(string.format("%q", original))
+ print("Channels not yet handled!\n")
+ else
+ if userlist[args[1]] then
+ userlist[args[1]].metadata[args[2]] = args[3]
+ else
+ print("Got metadata for an unknown user!\n")
+ end
+ end
+ end,
+
+ ["UID"] = function(con, source, args, original)
+ userlist[args[1]] = {
+ server = source,
+ nick_ts = args[2],
+ nick = args[3],
+ hostname = args[4],
+ vhost = args[5],
+ ident = args[6],
+ ip = args[7],
+ user_ts = args[8],
+ modes = {},
+ realname = args[-1], -- last one is safer as any extra are arguments to umodes (or protocol violations, but at that point nothing is a safe option)
+
+ metadata = {}, -- controlled by METADATA network commands
+ }
+
+ if not parse_modes(args[9], {table.unpack(args, 10, #args-1)}, {["s"] = {["+"] = true, ["-"] = false}}, userlist[args[1]].modes) then return true end
+ end,
+
+ ["OPERTYPE"] = function(con, source, args, original)
+ if userlist[source] then
+ userlist[source].opertype = args[1]
+ else
+ print("Server "..source.." attempted to set OPERTYPE on a nonexistent user!\n")
+ end
+ end,
+
+ ["NICK"] = function(con, source, args, original)
+ print(string.format("%q", original))
+ if userlist[source] then
+ userlist[source].nick = args[1]
+ userlist[source].nick_ts = args[2]
+ end
+ end,
+
+ ["PRIVMSG"] = function(con, source, args, original)
+ print(string.format("%q", original))
+ local cmd_args = {}
+ for part in args[2]:gmatch("[^ ]*") do
+ table.insert(cmd_args, part)
+ end
+ cmd = cmd_args[1]:upper()
+ table.remove(cmd_args, 1)
+
+ local resp
+ if args[1]:sub(1, 1) == "#" then
+ resp = args[1]
+
+ if cmd:sub(1, 1) ~= "-" then return end
+
+ cmd = cmd:sub(2) -- remove leading '-'
+ else
+ resp = source
+ end
+
+ if commands[cmd] then
+ if has_permission(userlist[source], commands[cmd].privs) then
+ return commands[cmd].func(con, source, cmd, cmd_args, resp)
+ else
+ con:send(":1HC000000 NOTICE "..resp.." :You are not authorized to execute that command.\n")
+ end
+ else
+ con:send(":1HC000000 NOTICE "..resp.." :Unknown command: "..cmd.."\n")
+ end
+ end,
+
+ ["MODE"] = function(con, source, args, original)
+ print(string.format("%q", original))
+ if args[1]:sub(1, 1) == "#" then
+ print("Channels not handled yet!\n")
+ else
+ if not userlist[args[1]] then
+ print("Attempted to set mode on an unknown user!\n")
+ elseif not parse_modes(args[2], {table.unpack(args, 3)}, {["s"] = {["+"] = true, ["-"] = false}}, userlist[args[1]].modes) then
+ return true
+ elseif not userlist[args[1]].modes.o then
+ userlist[args[1]].opertype = nil
+ end
+ end
+ end,
+
+ ["QUIT"] = function(con, source, args, original)
+ print(string.format("%q", original))
+ userlist[source] = nil
+ end,
+}