Mercurial > prosody-modules
comparison mod_ircd/mod_ircd.in.lua @ 468:640e6c0b563d
mod_ircd: Scrub invalid UTF-8 sequences, welcome message
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Tue, 01 Nov 2011 19:18:30 +0100 |
| parents | 0fcd34ee7301 |
| children | ff03a325aa41 |
comparison
equal
deleted
inserted
replaced
| 467:266bf13729ae | 468:640e6c0b563d |
|---|---|
| 51 --c.connect_host = "127.0.0.1" | 51 --c.connect_host = "127.0.0.1" |
| 52 --c:connect_component(component_jid, component_secret); | 52 --c:connect_component(component_jid, component_secret); |
| 53 | 53 |
| 54 local jid = require "util.jid"; | 54 local jid = require "util.jid"; |
| 55 local nodeprep = require "util.encodings".stringprep.nodeprep; | 55 local nodeprep = require "util.encodings".stringprep.nodeprep; |
| 56 | |
| 57 local function utf8_clean (s) | |
| 58 local push, join = table.insert, table.concat; | |
| 59 local r, i = {}, 1; | |
| 60 if not(s and #s > 0) then | |
| 61 return "" | |
| 62 end | |
| 63 while true do | |
| 64 local c = s:sub(i,i) | |
| 65 local b = c:byte(); | |
| 66 local w = ( | |
| 67 (b >= 9 and b <= 10 and 0) or | |
| 68 (b >= 32 and b <= 126 and 0) or | |
| 69 (b >= 192 and b <= 223 and 1) or | |
| 70 (b >= 224 and b <= 239 and 2) or | |
| 71 (b >= 240 and b <= 247 and 3) or | |
| 72 (b >= 248 and b <= 251 and 4) or | |
| 73 (b >= 251 and b <= 252 and 5) or nil | |
| 74 ) | |
| 75 if not w then | |
| 76 push(r, "?") | |
| 77 else | |
| 78 local n = i + w; | |
| 79 if w == 0 then | |
| 80 push(r, c); | |
| 81 elseif n > #s then | |
| 82 push(r, ("?"):format(b)); | |
| 83 else | |
| 84 local e = s:sub(i+1,n); | |
| 85 if e:match('^[\128-\191]*$') then | |
| 86 push(r, c); | |
| 87 push(r, e); | |
| 88 i = n; | |
| 89 else | |
| 90 push(r, ("?"):format(b)); | |
| 91 end | |
| 92 end | |
| 93 end | |
| 94 i = i + 1; | |
| 95 if i > #s then | |
| 96 break | |
| 97 end | |
| 98 end | |
| 99 return join(r); | |
| 100 end | |
| 56 | 101 |
| 57 local function parse_line(line) | 102 local function parse_line(line) |
| 58 local ret = {}; | 103 local ret = {}; |
| 59 if line:sub(1,1) == ":" then | 104 if line:sub(1,1) == ":" then |
| 60 ret.from, line = line:match("^:(%w+)%s+(.*)$"); | 105 ret.from, line = line:match("^:(%w+)%s+(.*)$"); |
| 126 end | 171 end |
| 127 command = command:upper(); | 172 command = command:upper(); |
| 128 if not session.nick then | 173 if not session.nick then |
| 129 if not (command == "USER" or command == "NICK") then | 174 if not (command == "USER" or command == "NICK") then |
| 130 module:log("debug", "Client tried to send command %s before registering", command); | 175 module:log("debug", "Client tried to send command %s before registering", command); |
| 131 return session.send{from=muc_server, 451, command, "You have not registered"} | 176 return session.send{from=muc_server, "451", command, "You have not registered"} |
| 132 end | 177 end |
| 133 end | 178 end |
| 134 if commands[command] then | 179 if commands[command] then |
| 135 local ret = commands[command](session, parts); | 180 local ret = commands[command](session, parts); |
| 136 if ret then | 181 if ret then |
| 137 return session.send(ret); | 182 return session.send(ret); |
| 138 end | 183 end |
| 139 else | 184 else |
| 140 session.send{from=muc_server, 421, session.nick, command, "Unknown command"}; | 185 session.send{from=muc_server, "421", session.nick, command, "Unknown command"}; |
| 141 return module:log("debug", "Unknown command: %s", command); | 186 return module:log("debug", "Unknown command: %s", command); |
| 142 end | 187 end |
| 143 end | 188 end |
| 144 function session.send(data) | 189 function session.send(data) |
| 145 if type(data) == "string" then | 190 if type(data) == "string" then |
| 172 sessions[conn] = nil; | 217 sessions[conn] = nil; |
| 173 end | 218 end |
| 174 | 219 |
| 175 function commands.NICK(session, args) | 220 function commands.NICK(session, args) |
| 176 if session.nick then | 221 if session.nick then |
| 177 session.send(":"..muc_server.." 484 * "..nick.." :I'm afraid I can't let you do that, "..session.nick); | 222 session.send{from = muc_server, "484", "*", nick, "I'm afraid I can't let you do that"}; |
| 178 --TODO Loop throug all rooms and change nick, with help from Verse. | 223 --TODO Loop throug all rooms and change nick, with help from Verse. |
| 179 return; | 224 return; |
| 180 end | 225 end |
| 181 local nick = args[1]; | 226 local nick = args[1]; |
| 182 nick = nick:gsub("[^%w_]",""); | 227 nick = nick:gsub("[^%w_]",""); |
| 183 if nicks[nick] then | 228 if nicks[nick] then |
| 184 session.send{from=muc_server, 433, nick, "The nickname "..nick.." is already in use"}; | 229 session.send{from=muc_server, "433", nick, "The nickname "..nick.." is already in use"}; |
| 185 return; | 230 return; |
| 186 end | 231 end |
| 187 local full_jid = jid.join(nick, component_jid, "ircd"); | 232 local full_jid = jid.join(nick, component_jid, "ircd"); |
| 188 jids[full_jid] = session; | 233 jids[full_jid] = session; |
| 189 nicks[nick] = session; | 234 nicks[nick] = session; |
| 190 session.nick = nick; | 235 session.nick = nick; |
| 191 session.full_jid = full_jid; | 236 session.full_jid = full_jid; |
| 192 session.type = "c2s"; | 237 session.type = "c2s"; |
| 193 session.send{from = muc_server, 001, nick, "Welcome to XMPP via the "..session.host.." gateway "..session.nick}; | 238 session.send{from = muc_server, "001", nick, "Welcome to IRC gateway to XMPP!"}; |
| 194 session.send{from=nick, "MODE", nick, "+i"}; -- why | 239 session.send{from = muc_server, "002", nick, module.host.." running Prosody "..prosody.version}; |
| 240 session.send{from = muc_server, "003", nick, os.date(nil, prosody.start_time)} | |
| 241 session.send{from = muc_server, "004", table.concat({muc_server, "alpha", "i", "ov"}, " ")}; | |
| 242 session.send{from = nick, "MODE", nick, "+i"}; -- why | |
| 195 end | 243 end |
| 196 | 244 |
| 197 function commands.USER(session, params) | 245 function commands.USER(session, params) |
| 198 -- FIXME | 246 -- FIXME |
| 199 -- Empty command for now | 247 -- Empty command for now |
| 278 local channel, message = unpack(args); | 326 local channel, message = unpack(args); |
| 279 if message and #message > 0 then | 327 if message and #message > 0 then |
| 280 if message:sub(1,8) == "\1ACTION " then | 328 if message:sub(1,8) == "\1ACTION " then |
| 281 message = "/me ".. message:sub(9,-2) | 329 message = "/me ".. message:sub(9,-2) |
| 282 end | 330 end |
| 283 -- TODO clean out invalid chars | 331 message = utf8_clean(message); |
| 284 if channel:sub(1,1) == "#" then | 332 if channel:sub(1,1) == "#" then |
| 285 if session.rooms[channel] then | 333 if session.rooms[channel] then |
| 286 module:log("debug", "%s sending PRIVMSG \"%s\" to %s", session.nick, message, channel); | 334 module:log("debug", "%s sending PRIVMSG \"%s\" to %s", session.nick, message, channel); |
| 287 session.rooms[channel]:send_message(message); | 335 session.rooms[channel]:send_message(message); |
| 288 end | 336 end |
| 320 end | 368 end |
| 321 session.send{from=muc_server, 315, session.nick, channel, "End of /WHO list"}; | 369 session.send{from=muc_server, 315, session.nick, channel, "End of /WHO list"}; |
| 322 end | 370 end |
| 323 end | 371 end |
| 324 | 372 |
| 325 function commands._MODE(session, args) -- FIXME | 373 function commands.MODE(session, args) -- FIXME |
| 326 local channel, target = unpack(args); | 374 local channel, target = unpack(args); |
| 327 if target then | 375 if target then |
| 328 -- do stuff? | 376 -- do stuff? |
| 329 --room:set_affiliation(...) | 377 --room:set_affiliation(...) |
| 378 session.send{from=muc_server, "324", session.nick, channel, "+i"} | |
| 330 else | 379 else |
| 331 -- What's 324? And +J ? | 380 -- What's 324? And +J ? |
| 332 session.send{from=muc_server, 324, session.nick, channel, "+J"} | 381 session.send{from=muc_server, "324", session.nick, channel, "+J"} |
| 333 end | 382 end |
| 334 end | 383 end |
| 335 | 384 |
| 336 function commands.QUIT(session, args) | 385 function commands.QUIT(session, args) |
| 337 session.send{"ERROR", "Closing Link: "..session.nick}; | 386 session.send{"ERROR", "Closing Link: "..session.nick}; |
