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