Merge 0.10->trunk
[prosody.git] / util / jid.lua
1 -- Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 --
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8
9
10
11 local select = select;
12 local match, sub = string.match, string.sub;
13 local nodeprep = require "util.encodings".stringprep.nodeprep;
14 local nameprep = require "util.encodings".stringprep.nameprep;
15 local resourceprep = require "util.encodings".stringprep.resourceprep;
16
17 local escapes = {
18         [" "] = "\\20"; ['"'] = "\\22";
19         ["&"] = "\\26"; ["'"] = "\\27";
20         ["/"] = "\\2f"; [":"] = "\\3a";
21         ["<"] = "\\3c"; [">"] = "\\3e";
22         ["@"] = "\\40"; ["\\"] = "\\5c";
23 };
24 local unescapes = {};
25 for k,v in pairs(escapes) do unescapes[v] = k; end
26
27 local _ENV = nil;
28
29 local function split(jid)
30         if not jid then return; end
31         local node, nodepos = match(jid, "^([^@/]+)@()");
32         local host, hostpos = match(jid, "^([^@/]+)()", nodepos)
33         if node and not host then return nil, nil, nil; end
34         local resource = match(jid, "^/(.+)$", hostpos);
35         if (not host) or ((not resource) and #jid >= hostpos) then return nil, nil, nil; end
36         return node, host, resource;
37 end
38
39 local function bare(jid)
40         local node, host = split(jid);
41         if node and host then
42                 return node.."@"..host;
43         end
44         return host;
45 end
46
47 local function prepped_split(jid)
48         local node, host, resource = split(jid);
49         if host then
50                 if sub(host, -1, -1) == "." then -- Strip empty root label
51                         host = sub(host, 1, -2);
52                 end
53                 host = nameprep(host);
54                 if not host then return; end
55                 if node then
56                         node = nodeprep(node);
57                         if not node then return; end
58                 end
59                 if resource then
60                         resource = resourceprep(resource);
61                         if not resource then return; end
62                 end
63                 return node, host, resource;
64         end
65 end
66
67 local function join(node, host, resource)
68         if not host then return end
69         if node and resource then
70                 return node.."@"..host.."/"..resource;
71         elseif node then
72                 return node.."@"..host;
73         elseif resource then
74                 return host.."/"..resource;
75         end
76         return host;
77 end
78
79 local function prep(jid)
80         local node, host, resource = prepped_split(jid);
81         return join(node, host, resource);
82 end
83
84 local function compare(jid, acl)
85         -- compare jid to single acl rule
86         -- TODO compare to table of rules?
87         local jid_node, jid_host, jid_resource = split(jid);
88         local acl_node, acl_host, acl_resource = split(acl);
89         if ((acl_node ~= nil and acl_node == jid_node) or acl_node == nil) and
90                 ((acl_host ~= nil and acl_host == jid_host) or acl_host == nil) and
91                 ((acl_resource ~= nil and acl_resource == jid_resource) or acl_resource == nil) then
92                 return true
93         end
94         return false
95 end
96
97 local function node(jid)
98         return (select(1, split(jid)));
99 end
100
101 local function host(jid)
102         return (select(2, split(jid)));
103 end
104
105 local function resource(jid)
106         return (select(3, split(jid)));
107 end
108
109 local function escape(s) return s and (s:gsub(".", escapes)); end
110 local function unescape(s) return s and (s:gsub("\\%x%x", unescapes)); end
111
112 return {
113         split = split;
114         bare = bare;
115         prepped_split = prepped_split;
116         join = join;
117         prep = prep;
118         compare = compare;
119         node = node;
120         host = host;
121         resource = resource;
122         escape = escape;
123         unescape = unescape;
124 };