mirror of
https://github.com/ShadowNinja/LuaIRC.git
synced 2025-01-09 17:40:29 +01:00
Add support for tag escapes
This commit is contained in:
parent
81d28bf4dc
commit
c27e2ec7e9
7
init.lua
7
init.lua
@ -178,7 +178,9 @@ function meta:think()
|
|||||||
local line = getline(self, 3)
|
local line = getline(self, 3)
|
||||||
if line and #line > 0 then
|
if line and #line > 0 then
|
||||||
if not self:invoke("OnRaw", line) then
|
if not self:invoke("OnRaw", line) then
|
||||||
self:handle(parse(line))
|
local msg = Message()
|
||||||
|
msg:fromRFC1459(line)
|
||||||
|
self:handle(msg)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
@ -227,7 +229,8 @@ function meta:whois(nick)
|
|||||||
while true do
|
while true do
|
||||||
local line = getline(self, 3)
|
local line = getline(self, 3)
|
||||||
if line then
|
if line then
|
||||||
local msg = parse(line)
|
local msg = Message()
|
||||||
|
msg:fromRFC1249(line)
|
||||||
|
|
||||||
local handler = whoisHandlers[msg.command]
|
local handler = whoisHandlers[msg.command]
|
||||||
if handler then
|
if handler then
|
||||||
|
73
messages.lua
73
messages.lua
@ -2,6 +2,7 @@ local assert = assert
|
|||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
local unpack = unpack
|
local unpack = unpack
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
|
local insert = table.insert
|
||||||
|
|
||||||
module "irc"
|
module "irc"
|
||||||
|
|
||||||
@ -17,6 +18,18 @@ function Message(cmd, args)
|
|||||||
}, msg_meta)
|
}, msg_meta)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local tag_escapes = {
|
||||||
|
[";"] = "\\:",
|
||||||
|
[" "] = "\\s",
|
||||||
|
["\0"] = "\\0",
|
||||||
|
["\\"] = "\\\\",
|
||||||
|
["\r"] = "\\r",
|
||||||
|
["\n"] = "\\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
local tag_unescapes = {}
|
||||||
|
for x, y in pairs(tag_escapes) do tag_unescapes[y] = x end
|
||||||
|
|
||||||
function msg_meta:toRFC1459()
|
function msg_meta:toRFC1459()
|
||||||
s = ""
|
s = ""
|
||||||
|
|
||||||
@ -25,10 +38,7 @@ function msg_meta:toRFC1459()
|
|||||||
for key, value in pairs(self.tags) do
|
for key, value in pairs(self.tags) do
|
||||||
s = s..key
|
s = s..key
|
||||||
if value ~= true then
|
if value ~= true then
|
||||||
assert(not value:find("[%z\07\r\n; ]"),
|
value = value:gsub("[; %z\\\r\n]", tag_escapes)
|
||||||
"NUL, BELL, CR, LF, semicolon, and"
|
|
||||||
.." space are not allowed in RFC1459"
|
|
||||||
.." formated tag values.")
|
|
||||||
s = s.."="..value
|
s = s.."="..value
|
||||||
end
|
end
|
||||||
s = s..";"
|
s = s..";"
|
||||||
@ -59,6 +69,55 @@ function msg_meta:toRFC1459()
|
|||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function parsePrefix(prefix)
|
||||||
|
local user = {}
|
||||||
|
user.nick, user.username, user.host = prefix:match("^(.+)!(.+)@(.+)$")
|
||||||
|
if not user.nick and prefix:find(".", 1, true) then
|
||||||
|
user.server = prefix
|
||||||
|
end
|
||||||
|
return user
|
||||||
|
end
|
||||||
|
|
||||||
|
function msg_meta:fromRFC1459(line)
|
||||||
|
-- IRCv3 tags
|
||||||
|
if line:sub(1, 1) == "@" then
|
||||||
|
self.tags = {}
|
||||||
|
local space = line:find(" ", 1, true)
|
||||||
|
-- For each semicolon-delimited section from after
|
||||||
|
-- the @ character to before the space character.
|
||||||
|
for tag in line:sub(2, space - 1):gmatch("([^;]+)") do
|
||||||
|
local eq = tag:find("=", 1, true)
|
||||||
|
if eq then
|
||||||
|
self.tags[tag:sub(1, eq - 1)] =
|
||||||
|
tag:sub(eq + 1):gsub("\\([:s0\\rn])", tag_unescapes)
|
||||||
|
else
|
||||||
|
self.tags[tag] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
line = line:sub(space + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
if line:sub(1, 1) == ":" then
|
||||||
|
local space = line:find(" ", 1, true)
|
||||||
|
self.prefix = line:sub(2, space - 1)
|
||||||
|
self.user = parsePrefix(self.prefix)
|
||||||
|
line = line:sub(space + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos
|
||||||
|
self.command, pos = line:match("(%S+)()")
|
||||||
|
line = line:sub(pos)
|
||||||
|
|
||||||
|
for pos, param in line:gmatch("()(%S+)") do
|
||||||
|
if param:sub(1, 1) == ":" then
|
||||||
|
param = line:sub(pos + 1)
|
||||||
|
insert(self.args, param)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
insert(self.args, param)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function msgs.privmsg(to, text)
|
function msgs.privmsg(to, text)
|
||||||
return Message("PRIVMSG", {to, text})
|
return Message("PRIVMSG", {to, text})
|
||||||
end
|
end
|
||||||
@ -135,9 +194,9 @@ end
|
|||||||
function msgs.mode(target, modes)
|
function msgs.mode(target, modes)
|
||||||
-- We have to split the modes parameter because the mode string and
|
-- We have to split the modes parameter because the mode string and
|
||||||
-- each parameter are seperate arguments (The first command is incorrect)
|
-- each parameter are seperate arguments (The first command is incorrect)
|
||||||
-- MODE :+ov Nick1 Nick2
|
-- MODE foo :+ov Nick1 Nick2
|
||||||
-- MODE +ov Nick1 Nick2
|
-- MODE foo +ov Nick1 Nick2
|
||||||
mt = split(modes)
|
local mt = split(modes)
|
||||||
return Message("MODE", {target, unpack(mt)})
|
return Message("MODE", {target, unpack(mt)})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
52
util.lua
52
util.lua
@ -10,49 +10,6 @@ local random = math.random
|
|||||||
|
|
||||||
module "irc"
|
module "irc"
|
||||||
|
|
||||||
-- Protocol parsing
|
|
||||||
function parse(line)
|
|
||||||
local msg = Message()
|
|
||||||
|
|
||||||
-- IRCv3 tags
|
|
||||||
if line:sub(1, 1) == "@" then
|
|
||||||
msg.tags = {}
|
|
||||||
local space = line:find(" ", 1, true)
|
|
||||||
-- For each semicolon-delimited section from after
|
|
||||||
-- the @ character to before the space character.
|
|
||||||
for tag in line:sub(2, space - 1):gmatch("([^;]+)") do
|
|
||||||
local eq = tag:find("=", 1, true)
|
|
||||||
if eq then
|
|
||||||
msg.tags[tag:sub(1, eq - 1)] = tag:sub(eq + 1)
|
|
||||||
else
|
|
||||||
msg.tags[tag] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
line = line:sub(space + 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
if line:sub(1, 1) == ":" then
|
|
||||||
local space = line:find(" ", 1, true)
|
|
||||||
msg.prefix = line:sub(2, space - 1)
|
|
||||||
msg.user = parsePrefix(msg.prefix)
|
|
||||||
line = line:sub(space + 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
local pos
|
|
||||||
msg.command, pos = line:match("(%S+)()")
|
|
||||||
line = line:sub(pos)
|
|
||||||
|
|
||||||
for pos, param in line:gmatch("()(%S+)") do
|
|
||||||
if param:sub(1, 1) == ":" then
|
|
||||||
param = line:sub(pos + 1)
|
|
||||||
table.insert(msg.args, param)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
table.insert(msg.args, param)
|
|
||||||
end
|
|
||||||
|
|
||||||
return msg
|
|
||||||
end
|
|
||||||
|
|
||||||
function parseNick(conn, nick)
|
function parseNick(conn, nick)
|
||||||
local access = {}
|
local access = {}
|
||||||
@ -73,15 +30,6 @@ function parseNick(conn, nick)
|
|||||||
return access, name
|
return access, name
|
||||||
end
|
end
|
||||||
|
|
||||||
function parsePrefix(prefix)
|
|
||||||
local user = {}
|
|
||||||
user.nick, user.username, user.host = prefix:match("^(.+)!(.+)@(.+)$")
|
|
||||||
if not user.nick and prefix:find(".", 1, true) then
|
|
||||||
user.server = prefix
|
|
||||||
end
|
|
||||||
return user
|
|
||||||
end
|
|
||||||
|
|
||||||
function updatePrefixModes(conn)
|
function updatePrefixModes(conn)
|
||||||
if conn.prefixmode and conn.modeprefix then
|
if conn.prefixmode and conn.modeprefix then
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user