1-- Prosody IM
2-- Copyright (C) 2008-2017 Matthew Wild
3-- Copyright (C) 2008-2017 Waqas Hussain
4-- Copyright (C) 2011-2017 Kim Alvefur
5--
6-- This project is MIT/X11 licensed. Please see the
7-- COPYING file in the source package for more information.
8--
9-- XEP-0313: Message Archive Management for Prosody
10--
11
12local stanza = require"util.stanza".stanza;
13local tostring, tonumber = tostring, tonumber;
14local type = type;
15local pairs = pairs;
16
17local xmlns_rsm = 'http://jabber.org/protocol/rsm';
18
19local element_parsers = {};
20
21do
22	local parsers = element_parsers;
23	local function xs_int(st)
24		return tonumber((st:get_text()));
25	end
26	local function xs_string(st)
27		return st:get_text();
28	end
29
30	parsers.after = xs_string;
31	parsers.before = function(st)
32			local text = st:get_text();
33			return text == "" or text;
34		end;
35	parsers.max = xs_int;
36	parsers.index = xs_int;
37
38	parsers.first = function(st)
39			return { index = tonumber(st.attr.index); st:get_text() };
40		end;
41	parsers.last = xs_string;
42	parsers.count = xs_int;
43end
44
45local element_generators = setmetatable({
46	first = function(st, data)
47		if type(data) == "table" then
48			st:tag("first", { index = data.index }):text(data[1]):up();
49		else
50			st:tag("first"):text(tostring(data)):up();
51		end
52	end;
53	before = function(st, data)
54		if data == true then
55			st:tag("before"):up();
56		else
57			st:tag("before"):text(tostring(data)):up();
58		end
59	end
60}, {
61	__index = function(_, name)
62		return function(st, data)
63			st:tag(name):text(tostring(data)):up();
64		end
65	end;
66});
67
68
69local function parse(set)
70	local rs = {};
71	for tag in set:childtags() do
72		local name = tag.name;
73		local parser = name and element_parsers[name];
74		if parser then
75			rs[name] = parser(tag);
76		end
77	end
78	return rs;
79end
80
81local function generate(t)
82	local st = stanza("set", { xmlns = xmlns_rsm });
83	for k,v in pairs(t) do
84		if element_parsers[k] then
85			element_generators[k](st, v);
86		end
87	end
88	return st;
89end
90
91local function get(st)
92	local set = st:get_child("set", xmlns_rsm);
93	if set and #set.tags > 0 then
94		return parse(set);
95	end
96end
97
98return { parse = parse, generate = generate, get = get };
99