Software /
code /
prosody-modules
Comparison
mod_storage_xmlarchive/mod_storage_xmlarchive.lua @ 3898:e9e19b9a6a55
mod_storage_xmlarchive: Add a new API similar to map-stores
This can be used to replace messages with tombstones
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 22 Feb 2020 21:12:29 +0100 |
parent | 3755:bb18a1f5e9d7 |
child | 3899:a03abb4bb6d7 |
comparison
equal
deleted
inserted
replaced
3897:3a96070f4a14 | 3898:e9e19b9a6a55 |
---|---|
9 local dm = require "core.storagemanager".olddm; | 9 local dm = require "core.storagemanager".olddm; |
10 local hmac_sha256 = require"util.hashes".hmac_sha256; | 10 local hmac_sha256 = require"util.hashes".hmac_sha256; |
11 local st = require"util.stanza"; | 11 local st = require"util.stanza"; |
12 local dt = require"util.datetime"; | 12 local dt = require"util.datetime"; |
13 local new_stream = require "util.xmppstream".new; | 13 local new_stream = require "util.xmppstream".new; |
14 local xml = require "util.xml"; | |
14 local empty = {}; | 15 local empty = {}; |
15 | 16 |
16 if not dm.append_raw then | 17 if not dm.append_raw then |
17 module:require"datamanager_append_raw"; | 18 module:require"datamanager_append_raw"; |
18 end | 19 end |
55 end | 56 end |
56 if not ok then | 57 if not ok then |
57 return nil, err; | 58 return nil, err; |
58 end | 59 end |
59 return id; | 60 return id; |
61 end | |
62 | |
63 function archive:get(username, id) | |
64 local dates = self:dates(username) or empty; | |
65 local day_idx, item_idx, items = self:_get_idx(username, id, dates); | |
66 if not day_idx then | |
67 return nil, "item-not-found"; | |
68 end | |
69 module:log("debug", ":_get_idx(%q, %q) --> %q, %q", username, id, dates[day_idx], items[item_idx]); | |
70 local day = dates[day_idx]; | |
71 local item = items[item_idx]; | |
72 module:log("debug", "item = %q", item); | |
73 local filename = dm.getpath(username.."@"..day, self.host, self.store, "xml"); | |
74 local xmlfile, ferr = io.open(filename, "r"); | |
75 if not xmlfile then return nil, ferr; end | |
76 local p,err = xmlfile:seek("set", item.offset); | |
77 if p ~= item.offset or err ~= nil then return nil, err; end | |
78 local data = xmlfile:read(item.length); | |
79 local parsed, perr = xml.parse(data); | |
80 if not parsed then return nil, perr; end | |
81 return parsed, dt.parse(item.when), item.with; | |
82 end | |
83 | |
84 local overwrite = module:get_option("xmlarchive_overwrite", false); | |
85 | |
86 function archive:set(username, id, data, new_when, new_with) | |
87 if not is_stanza(data) then | |
88 module:log("error", "Attempt to store non-stanza object, traceback: %s", debug.traceback()); | |
89 return nil, "unsupported-datatype"; | |
90 end | |
91 | |
92 username = username or "@"; | |
93 data = tostring(data) .. "\n"; | |
94 | |
95 local dates = self:dates(username) or empty; | |
96 local day_idx, item_idx, items = self:_get_idx(username, id, dates); | |
97 if not day_idx then | |
98 return nil, "item-not-found"; | |
99 end | |
100 local day = dates[day_idx]; | |
101 local item = items[item_idx]; | |
102 | |
103 local filename = dm.getpath(username.."@"..day, self.host, self.store, "xml"); | |
104 | |
105 local replaced, err = dm.append_raw(username.."@"..day, self.host, self.store, "xml", data); | |
106 if not replaced then return nil, err; end | |
107 local new_offset = err; | |
108 | |
109 -- default yes or no? | |
110 if overwrite then | |
111 local xmlfile, ferr = io.open(filename, "r+"); | |
112 if not xmlfile then return nil, ferr; end | |
113 local p,err = xmlfile:seek("set", item.offset); | |
114 if p ~= item.offset or err ~= nil then return nil, err; end | |
115 local _,err = xmlfile:write((" "):rep(item.length)); | |
116 if err ~= nil then return nil, err; end | |
117 local _,err = xmlfile:close(); | |
118 if err ~= nil then return nil, err; end | |
119 end | |
120 | |
121 items[item_idx] = { | |
122 id = id, | |
123 when = new_when or item.when, | |
124 with = new_with or item.with, | |
125 offset = new_offset, | |
126 length = #data, | |
127 replaces = item, | |
128 }; | |
129 local ok, err = dm.list_store(username.."@"..day, self.host, self.store, items); | |
130 return ok, err; | |
60 end | 131 end |
61 | 132 |
62 function archive:_get_idx(username, id, dates) | 133 function archive:_get_idx(username, id, dates) |
63 module:log("debug", "Looking for item with id %q", id); | 134 module:log("debug", "Looking for item with id %q", id); |
64 dates = dates or self:dates(username) or empty; | 135 dates = dates or self:dates(username) or empty; |
327 function module.command(arg) | 398 function module.command(arg) |
328 local jid = require "util.jid"; | 399 local jid = require "util.jid"; |
329 if arg[1] == "convert" and (arg[2] == "to" or arg[2] == "from") and arg[4] then | 400 if arg[1] == "convert" and (arg[2] == "to" or arg[2] == "from") and arg[4] then |
330 local convert; | 401 local convert; |
331 if arg[2] == "to" then | 402 if arg[2] == "to" then |
332 local xml = require "util.xml"; | |
333 function convert(user, host, store) | 403 function convert(user, host, store) |
334 local dates, err = archive.dates({ host = host, store = store }, user); | 404 local dates, err = archive.dates({ host = host, store = store }, user); |
335 if not dates then assert(not err, err); return end | 405 if not dates then assert(not err, err); return end |
336 assert(dm.list_store(user, host, store, nil)); | 406 assert(dm.list_store(user, host, store, nil)); |
337 for _, date in ipairs(dates) do | 407 for _, date in ipairs(dates) do |