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