]> git.lizzy.rs Git - luairc.git/blob - src/irc/ctcp.lua
Port to Lua 5.3
[luairc.git] / src / irc / ctcp.lua
1 ---
2 -- Implementation of the CTCP protocol
3
4 ---
5 -- This module implements the various quoting and escaping requirements of the
6 -- CTCP protocol.
7 local ctcp = {}
8
9 -- internal functions {{{
10 -- _low_quote {{{
11 --
12 -- Applies low level quoting to a string (escaping characters which are illegal
13 -- to appear in an IRC packet).
14 -- @param ... Strings to quote together, space separated
15 -- @return Quoted string
16 function ctcp._low_quote(...)
17     local str = table.concat({...}, " ")
18     return str:gsub("[%z\n\r\020]", {["\000"] = "\0200",
19                                      ["\n"]   = "\020n",
20                                      ["\r"]   = "\020r",
21                                      ["\020"] = "\020\020"})
22 end
23 -- }}}
24
25 -- _low_dequote {{{
26 --
27 -- Removes low level quoting done by low_quote.
28 -- @param str String with low level quoting applied to it
29 -- @return String with those quoting methods stripped off
30 function ctcp._low_dequote(str)
31     return str:gsub("\020(.?)", function(s)
32                                     if s == "0" then return "\000" end
33                                     if s == "n" then return "\n" end
34                                     if s == "r" then return "\r" end
35                                     if s == "\020" then return "\020" end
36                                     return ""
37                                 end)
38 end
39 -- }}}
40
41 -- _ctcp_quote {{{
42 --
43 -- Applies CTCP quoting to a block of text which has been identified as CTCP
44 -- data (by the calling program).
45 -- @param ... Strings to apply CTCP quoting to together, space separated
46 -- @return String with CTCP quoting applied
47 function ctcp._ctcp_quote(...)
48     local str = table.concat({...}, " ")
49     local ret = str:gsub("[\001\\]", {["\001"] = "\\a",
50                                       ["\\"]   = "\\\\"})
51     return "\001" .. ret .. "\001"
52 end
53 -- }}}
54
55 -- _ctcp_dequote {{{
56 --
57 -- Removes CTCP quoting from a block of text which has been identified as CTCP
58 -- data (likely by ctcp_split).
59 -- @param str String with CTCP quoting
60 -- @return String with all CTCP quoting stripped
61 function ctcp._ctcp_dequote(str)
62     local ret = str:gsub("^\001", ""):gsub("\001$", "")
63     return ret:gsub("\\(.?)", function(s)
64                                   if s == "a" then return "\001" end
65                                   if s == "\\" then return "\\" end
66                                   return ""
67                               end)
68 end
69 -- }}}
70
71 -- _ctcp_split {{{
72 --
73 -- Splits a low level dequoted string into normal text and unquoted CTCP
74 -- messages.
75 -- @param str Low level dequoted string
76 -- @return Array of tables, with each entry in the array corresponding to one
77 --         part of the split message. These tables will have these fields:
78 --         <ul>
79 --         <li><i>str:</i>  The text of the split section</li>
80 --         <li><i>ctcp:</i> True if the section was a CTCP message, false
81 --                          otherwise</li>
82 --         </ul>
83 function ctcp._ctcp_split(str)
84     local ret = {}
85     local iter = 1
86     while true do
87         local s, e = str:find("\001.*\001", iter)
88
89         local plain_string, ctcp_string
90         if not s then
91             plain_string = str:sub(iter, -1)
92         else
93             plain_string = str:sub(iter, s - 1)
94             ctcp_string = str:sub(s, e)
95         end
96
97         if plain_string ~= "" then
98             table.insert(ret, {str = plain_string, ctcp = false})
99         end
100         if not s then break end
101         if ctcp_string ~= "" then
102             table.insert(ret, {str = ctcp._ctcp_dequote(ctcp_string), ctcp = true})
103         end
104
105         iter = e + 1
106     end
107
108     return ret
109 end
110 -- }}}
111 -- }}}
112
113 return ctcp