TT#9400 use quilt to maintain patches to upstream

- wrap-and-sort -sat
- add quilt as build dependence
- keep mod_auth_sql changes in quilt
- Revert "TT#9317 mod_mam: don't store bodyless chat messages"
  This reverts commit 7fc4d61ef3.

- Revert "TT#9311 mod_mam/sipwise_archive.lib: full username"
  This reverts commit b17aec94a0.

- Revert "TT#9303 mod_mam: sipwise_archive.lib fix crash at find()"
  This reverts commit 9e93fb6510.

- Revert "TT#8297 mam: implement archive to DB"
  This reverts commit 754fb5b63c.

- Revert "TT#7482 mod_man: support mam version 0.5 (urn:xmpp:mam:1)"
  This reverts commit 9e65f1029f.

Change-Id: I3e008843f16fdd03e8c3d2dbc4ccb2ac16e6dfe5
changes/83/10783/4
Victor Seva 8 years ago
parent 7fc4d61ef3
commit 0fbc57ef6e

23
debian/control vendored

@ -2,21 +2,24 @@ Source: ngcp-prosody-modules
Section: net
Priority: extra
Maintainer: Sipwise Development Team <support@sipwise.com>
Build-Depends: debhelper (>= 9~)
Build-Depends:
debhelper (>= 9~),
quilt,
Standards-Version: 3.9.7
Homepage: http://sipwise.com/
Package: ngcp-prosody-modules
Architecture: all
Depends: lua-bitop,
lua-dbi-common,
lua-dbi-mysql,
lua-redis,
lua-rex-pcre,
lua-sec,
ngcp-system-tools-ce | ngcp-system-tools,
prosody (>= 0.9.8~),
${misc:Depends},
Depends:
lua-bitop,
lua-dbi-common,
lua-dbi-mysql,
lua-redis,
lua-rex-pcre,
lua-sec,
ngcp-system-tools-ce | ngcp-system-tools,
prosody (>= 0.9.8~),
${misc:Depends},
Description: ngcp modules for the prosody Jabber/XMPP server
This package provides modules for the Prosody Jabber/XMPP server
Prosody, especially for usage with the Sipwise Next Generation

@ -0,0 +1,189 @@
From 9e65f1029f84b0336f5096f6e56b27cb117ec568 Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Mon, 26 Dec 2016 14:42:46 +0100
Subject: [PATCH] TT#7482 mod_man: support mam version 0.5 (urn:xmpp:mam:1)
* keep compability with mam version 0.3 (urn:xmpp:mam:0)
Change-Id: I03dcc49c39b5eb6c38e30d27bcc3b93b8137c770
---
plugins/mod_mam/mamprefsxml.lib.lua | 3 +-
plugins/mod_mam/mod_mam.lua | 80 +++++++++++++++++++++++++++++--------
2 files changed, 64 insertions(+), 19 deletions(-)
diff --git a/plugins/mod_mam/mamprefsxml.lib.lua b/plugins/mod_mam/mamprefsxml.lib.lua
index a0d4624..4b3a50b 100644
--- a/plugins/mod_mam/mamprefsxml.lib.lua
+++ b/plugins/mod_mam/mamprefsxml.lib.lua
@@ -4,7 +4,6 @@
-- This file is MIT/X11 licensed.
local st = require"util.stanza";
-local xmlns_mam = "urn:xmpp:mam:0";
local default_attrs = {
always = true, [true] = "always",
@@ -12,7 +11,7 @@ local default_attrs = {
roster = "roster",
}
-local function tostanza(prefs)
+local function tostanza(prefs, xmlns_mam)
local default = prefs[false];
default = default_attrs[default];
local prefstanza = st.stanza("prefs", { xmlns = xmlns_mam, default = default });
diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua
index fe69e33..dbdd92a 100644
--- a/plugins/mod_mam/mod_mam.lua
+++ b/plugins/mod_mam/mod_mam.lua
@@ -3,7 +3,8 @@
--
-- This file is MIT/X11 licensed.
-local xmlns_mam = "urn:xmpp:mam:0";
+local xmlns_mam0 = "urn:xmpp:mam:0";
+local xmlns_mam1 = "urn:xmpp:mam:1";
local xmlns_delay = "urn:xmpp:delay";
local xmlns_forward = "urn:xmpp:forward:0";
@@ -54,11 +55,11 @@ end
local cleanup;
-- Handle prefs.
-module:hook("iq/self/"..xmlns_mam..":prefs", function(event)
+local function handle_prefs(event, xmlns_mam)
local origin, stanza = event.origin, event.stanza;
local user = origin.username;
if stanza.attr.type == "get" then
- local prefs = prefs_to_stanza(get_prefs(user));
+ local prefs = prefs_to_stanza(get_prefs(user), xmlns_mam);
local reply = st.reply(stanza):add_child(prefs);
origin.send(reply);
else -- type == "set"
@@ -72,24 +73,47 @@ module:hook("iq/self/"..xmlns_mam..":prefs", function(event)
end
end
return true;
+end
+
+module:hook("iq/self/"..xmlns_mam1..":prefs", function(event)
+ return handle_prefs(event, xmlns_mam1)
+end);
+
+module:hook("iq/self/"..xmlns_mam0..":prefs", function(event)
+ return handle_prefs(event, xmlns_mam0)
end);
-local query_form = dataform {
- { name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam; };
+local query_form = {}
+query_form[xmlns_mam1] = dataform {
+ { name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam1; };
+ { name = "with"; type = "jid-single"; };
+ { name = "start"; type = "text-single" };
+ { name = "end"; type = "text-single"; };
+};
+query_form[xmlns_mam0] = dataform {
+ { name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam0; };
{ name = "with"; type = "jid-single"; };
{ name = "start"; type = "text-single" };
{ name = "end"; type = "text-single"; };
};
-- Serve form
-module:hook("iq-get/self/"..xmlns_mam..":query", function(event)
+local function get_form(event, xmlns_mam)
local origin, stanza = event.origin, event.stanza;
- origin.send(st.reply(stanza):add_child(query_form:form()));
+ origin.send(st.reply(stanza):add_child(query_form[xmlns_mam]:form()));
return true;
+end
+
+module:hook("iq-get/self/"..xmlns_mam1..":query", function(event)
+ return get_form(event, xmlns_mam1);
+end);
+
+module:hook("iq-get/self/"..xmlns_mam0..":query", function(event)
+ return get_form(event, xmlns_mam0);
end);
-- Handle archive queries
-module:hook("iq-set/self/"..xmlns_mam..":query", function(event)
+local function handle_query(event, xmlns_mam)
local origin, stanza = event.origin, event.stanza;
local query = stanza.tags[1];
local qid = query.attr.queryid;
@@ -101,7 +125,7 @@ module:hook("iq-set/self/"..xmlns_mam..":query", function(event)
local form = query:get_child("x", "jabber:x:data");
if form then
local err;
- form, err = query_form:data(form);
+ form, err = query_form[xmlns_mam]:data(form);
if err then
origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err))));
return true;
@@ -145,9 +169,13 @@ module:hook("iq-set/self/"..xmlns_mam..":query", function(event)
return true;
end
local total = tonumber(err);
+ local msg_reply_attr;
+
+ if xmlns_mam == xmlns_mam0 then
+ origin.send(st.reply(stanza));
+ msg_reply_attr = { to = stanza.attr.from, from = stanza.attr.to };
+ end
- origin.send(st.reply(stanza));
- local msg_reply_attr = { to = stanza.attr.from, from = stanza.attr.to };
local results = {};
@@ -192,11 +220,27 @@ module:hook("iq-set/self/"..xmlns_mam..":query", function(event)
-- That's all folks!
module:log("debug", "Archive query %s completed", tostring(qid));
- origin.send(st.message(msg_reply_attr)
- :tag("fin", { xmlns = xmlns_mam, queryid = qid, complete = complete })
- :add_child(rsm.generate {
- first = first, last = last, count = total }));
+ local reply_stanza;
+ if xmlns_mam == xmlns_mam0 then
+ reply_stanza = st.message(msg_reply_attr);
+ else
+ reply_stanza = st.reply(stanza);
+ end
+
+ if form or xmlns_mam == xmlns_mam0 then
+ reply_stanza:tag("fin",{ xmlns = xmlns_mam, queryid = qid, complete = complete })
+ :add_child(rsm.generate { first = first, last = last, count = total })
+ end
+ origin.send(reply_stanza);
return true;
+end
+
+module:hook("iq-set/self/"..xmlns_mam1..":query", function(event)
+ return handle_query(event, xmlns_mam1);
+end);
+
+module:hook("iq-set/self/"..xmlns_mam0..":query", function(event)
+ return handle_query(event, xmlns_mam0);
end);
local function has_in_roster(user, who)
@@ -330,9 +374,11 @@ module:hook("pre-message/full", c2s_message_handler, 2);
module:hook("message/bare", message_handler, 2);
module:hook("message/full", message_handler, 2);
-module:add_feature(xmlns_mam); -- COMPAT with XEP-0313 v 0.1
+module:add_feature(xmlns_mam0); -- COMPAT with XEP-0313 v 0.1
+module:add_feature(xmlns_mam1); -- COMPAT with XEP-0313 v 0.5
module:hook("account-disco-info", function(event)
- (event.reply or event.stanza):tag("feature", {var=xmlns_mam}):up();
+ (event.reply or event.stanza):tag("feature", {var=xmlns_mam0}):up();
+ (event.reply or event.stanza):tag("feature", {var=xmlns_mam1}):up();
end);
--
2.11.0

@ -0,0 +1,213 @@
From 754fb5b63c5d3b4125ec80b8ecfdfdd3676242b3 Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Tue, 3 Jan 2017 17:14:49 +0100
Subject: [PATCH] TT#8297 mam: implement archive to DB
Change-Id: If9644ac66fdd257a430cfb7fa185230c77cd783e
---
plugins/mod_mam/mod_mam.lua | 16 +---
plugins/mod_mam/sipwise_archive.lib.lua | 165 ++++++++++++++++++++++++++++++++
2 files changed, 166 insertions(+), 15 deletions(-)
create mode 100644 plugins/mod_mam/sipwise_archive.lib.lua
diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua
index dbdd92a..d7f4f61 100644
--- a/plugins/mod_mam/mod_mam.lua
+++ b/plugins/mod_mam/mod_mam.lua
@@ -37,21 +37,7 @@ if global_default_policy ~= "roster" then
global_default_policy = module:get_option_boolean("default_archive_policy", global_default_policy);
end
-local archive_store = "archive2";
-local archive = assert(module:open_store(archive_store, "archive"));
-
-if archive.name == "null" or not archive.find then
- if not archive.find then
- module:log("debug", "Attempt to open archive storage returned a valid driver but it does not seem to implement the storage API");
- module:log("debug", "mod_%s does not support archiving", archive._provided_by or archive.name and "storage_"..archive.name.."(?)" or "<unknown>");
- else
- module:log("debug", "Attempt to open archive storage returned null driver");
- end
- module:log("debug", "See https://prosody.im/doc/storage and https://prosody.im/doc/archiving for more information");
- module:log("info", "Using in-memory fallback archive driver");
- archive = module:require "fallback_archive";
-end
-
+local archive = module:require "sipwise_archive";
local cleanup;
-- Handle prefs.
diff --git a/plugins/mod_mam/sipwise_archive.lib.lua b/plugins/mod_mam/sipwise_archive.lib.lua
new file mode 100644
index 0000000..f772ea6
--- /dev/null
+++ b/plugins/mod_mam/sipwise_archive.lib.lua
@@ -0,0 +1,165 @@
+-- luacheck: ignore 212/self
+local uuid = require "util.uuid".generate;
+local archive_store = { _provided_by = "mam"; name = "fallback"; };
+
+local serialize = require "util.serialization".serialize;
+local deserialize = require "util.serialization".deserialize;
+local st = require "util.stanza";
+
+local mod_sql = module:require("sql");
+local params = module:get_option("sql", {});
+local engine = mod_sql:create_engine(params);
+engine:execute("SET NAMES 'utf8' COLLATE 'utf8_bin';");
+local log = require "util.logger".init("sipwise_archive");
+local ut_tostring = require "util.table".table.tostring;
+
+local store_query=[[
+INSERT INTO `sipwise_mam` (`username`, `key`, `stanza`, `epoch`, `with`)
+VALUES (?,UuidToBin(?),?,?,?);
+]]
+
+local delete_query=[[
+DELETE FROM `sipwise_mam`
+WHERE `username` = ?;
+]]
+
+local delete_query_extra=[[
+DELETE FROM `sipwise_mam`
+WHERE `username` = ? AND `epoch` <= ?;
+]]
+
+local select_key_query=[[
+SELECT id FROM `sipwise_mam`
+WHERE `key` = UuidToBin(?)
+]]
+
+local select_query_base=[[
+SELECT UuidFromBin(`key`),`stanza`,`epoch`,`with` FROM `sipwise_mam`
+WHERE `username` = ?
+]]
+
+-- Reconnect to DB if necessary
+local function reconect_check()
+ if not engine.conn:ping() then
+ engine.conn = nil;
+ log("debug", "DDBB reconecting");
+ engine:connect();
+ end
+end
+
+local function load_db(query, _params)
+ local res;
+ reconect_check();
+ log("debug", "query[%s]", query);
+ log("debug", "_params[%s]", ut_tostring(_params));
+ res = engine:select(query, unpack(_params));
+ local out = {};
+ for row in res do
+ table.insert(out, {row[1], row[2], row[3], row[4]});
+ end
+ return out;
+end
+
+local function key_get_id(key)
+ local res;
+ reconect_check();
+ res = engine:select(select_key_query, key);
+ local out = {};
+ for row in res do
+ table.insert(out, row[1]);
+ end
+ return out[1];
+end
+
+local function key_in_db(key)
+ local res = key_get_id(key);
+ if res then
+ return true;
+ else
+ return false;
+ end
+end
+
+function archive_store:append(username, key, value, when, with)
+ reconect_check();
+ if not key or key_in_db(key) then
+ key = uuid();
+ end
+ engine:insert(store_query, username, key, serialize(st.preserialize(value)),
+ when, with);
+ engine.conn:commit();
+end
+
+function archive_store:find(username, query)
+ local qstart, qend, qwith = -math.huge, math.huge;
+ local qlimit, qid;
+ local db_query = select_query_base;
+ local _params = { username, };
+ local i, values = 0;
+
+ if query then
+ if query.reverse then
+ if query.before then
+ qid = key_get_id(query.before);
+ end
+ elseif query.after then
+ qid = key_get_id(query.after);
+ end
+ qwith = query.with;
+ qlimit = query.limit;
+ qstart = query.start or qstart;
+ qend = query["end"] or qend;
+ end
+
+ if qwith then
+ db_query = db_query.." AND `with` = ?";
+ table.insert(_params, qwith);
+ end
+ if qid then
+ if query.reverse then
+ db_query = db_query.." AND `id` < ?";
+ else
+ db_query = db_query.." AND `id` > ?";
+ end
+ table.insert(_params, qid);
+ end
+ db_query = db_query.." AND (`epoch` >= ? AND `epoch` <= ?)";
+ table.insert(_params, qstart);
+ table.insert(_params, qend);
+ db_query = db_query.." ORDER BY `epoch`";
+ if query.reverse then
+ db_query = db_query.." DESC";
+ end
+ if qlimit then
+ db_query = db_query.." LIMIT ?";
+ table.insert(_params, qlimit);
+ end
+ db_query = db_query..";"
+ values = load_db(db_query, _params);
+
+ return function ()
+ i = i + 1;
+ if values[i] then
+ return values[i][1], deserialize(values[i][2]), values[i][3], values[i][4];
+ end
+ end
+end
+
+function archive_store:delete(username, query)
+ if not query or next(query) == nil then
+ -- no specifics, delete everything
+ reconect_check();
+ engine:delete(delete_query, username);
+ engine.conn:commit();
+ return true;
+ end
+
+ local qend = query["end"] or math.huge;
+
+ reconect_check();
+ engine:delete(delete_query_extra, username, qend);
+ engine.conn:commit();
+ return true;
+end
+
+return archive_store;
--
2.11.0

@ -0,0 +1,43 @@
From 9e93fb65101c48a62fec403541216f99e24a121a Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Thu, 19 Jan 2017 16:25:24 +0100
Subject: [PATCH] TT#9303 mod_mam: sipwise_archive.lib fix crash at find()
> mod_c2s: Traceback[c2s]: /usr/lib/prosody/util/sql.lua:189:
> Error executing statement parameters: Data too long for column '_uuid' at row 1
Change-Id: I9e7d6a310ee5e5e8f83cbc97cb2f7ebcf4f534b5
---
plugins/mod_mam/sipwise_archive.lib.lua | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/plugins/mod_mam/sipwise_archive.lib.lua b/plugins/mod_mam/sipwise_archive.lib.lua
index f772ea6..087c306 100644
--- a/plugins/mod_mam/sipwise_archive.lib.lua
+++ b/plugins/mod_mam/sipwise_archive.lib.lua
@@ -29,8 +29,8 @@ WHERE `username` = ? AND `epoch` <= ?;
]]
local select_key_query=[[
-SELECT id FROM `sipwise_mam`
-WHERE `key` = UuidToBin(?)
+SELECT `id` FROM `sipwise_mam`
+WHERE `key` = UuidToBin(?);
]]
local select_query_base=[[
@@ -63,6 +63,11 @@ end
local function key_get_id(key)
local res;
reconect_check();
+ -- key is an uuid
+ if string.len(key) ~= 36 then
+ log("warn", "key[%s] is not a proper uuid");
+ return nil;
+ end
res = engine:select(select_key_query, key);
local out = {};
for row in res do
--
2.11.0

@ -0,0 +1,67 @@
From b17aec94a0563c5fab58ed350c1e32787ae3f7fe Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Thu, 19 Jan 2017 16:38:26 +0100
Subject: [PATCH] TT#9311 mod_mam/sipwise_archive.lib: full username
* domain was not included
Change-Id: Id2bbc496545ba7c167cd4dacb24153708e826ca2
---
plugins/mod_mam/sipwise_archive.lib.lua | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/plugins/mod_mam/sipwise_archive.lib.lua b/plugins/mod_mam/sipwise_archive.lib.lua
index 087c306..46166f8 100644
--- a/plugins/mod_mam/sipwise_archive.lib.lua
+++ b/plugins/mod_mam/sipwise_archive.lib.lua
@@ -12,6 +12,7 @@ local engine = mod_sql:create_engine(params);
engine:execute("SET NAMES 'utf8' COLLATE 'utf8_bin';");
local log = require "util.logger".init("sipwise_archive");
local ut_tostring = require "util.table".table.tostring;
+local host = module.host;
local store_query=[[
INSERT INTO `sipwise_mam` (`username`, `key`, `stanza`, `epoch`, `with`)
@@ -90,7 +91,7 @@ function archive_store:append(username, key, value, when, with)
if not key or key_in_db(key) then
key = uuid();
end
- engine:insert(store_query, username, key, serialize(st.preserialize(value)),
+ engine:insert(store_query, username..'@'..host, key, serialize(st.preserialize(value)),
when, with);
engine.conn:commit();
end
@@ -99,7 +100,7 @@ function archive_store:find(username, query)
local qstart, qend, qwith = -math.huge, math.huge;
local qlimit, qid;
local db_query = select_query_base;
- local _params = { username, };
+ local _params = { username..'@'..host, };
local i, values = 0;
if query then
@@ -151,10 +152,11 @@ function archive_store:find(username, query)
end
function archive_store:delete(username, query)
+ local jid = username..'@'..host
if not query or next(query) == nil then
-- no specifics, delete everything
reconect_check();
- engine:delete(delete_query, username);
+ engine:delete(delete_query, jid);
engine.conn:commit();
return true;
end
@@ -162,7 +164,7 @@ function archive_store:delete(username, query)
local qend = query["end"] or math.huge;
reconect_check();
- engine:delete(delete_query_extra, username, qend);
+ engine:delete(delete_query_extra, jid, qend);
engine.conn:commit();
return true;
end
--
2.11.0

@ -0,0 +1,50 @@
From 7fc4d61ef370de25c69a0a637c0d0e2624e61dc0 Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Thu, 19 Jan 2017 17:13:12 +0100
Subject: [PATCH] TT#9317 mod_mam: don't store bodyless chat messages
* implement store hints https://prosody.im/issues/issue/750
Change-Id: I590b1fb9bd95afdce6a117778052d11d8102f718
---
plugins/mod_mam/mod_mam.lua | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua
index d7f4f61..bb604ed 100644
--- a/plugins/mod_mam/mod_mam.lua
+++ b/plugins/mod_mam/mod_mam.lua
@@ -267,11 +267,25 @@ local function message_handler(event, c2s)
local orig_from = stanza.attr.from;
local orig_to = stanza.attr.to or orig_from;
-- Stanza without 'to' are treated as if it was to their own bare jid
-
- -- We store chat messages or normal messages that have a body
- if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body")) ) then
- log("debug", "Not archiving stanza: %s (type)", stanza:top_tag());
- return;
+ local body = stanza:get_child("body");
+ local force_store = stanza:get_child("store", "urn:xmpp:hints");
+
+ if not force_store then
+ -- We store chat messages or normal messages that have a body
+ if not(orig_type == "chat" or (orig_type == "normal" and body)) then
+ log("debug", "Not archiving stanza: %s (type)", stanza:top_tag());
+ return;
+ elseif (orig_type == 'chat' and not body) then
+ log("debug", "Not archiving stanza: %s (type), has no body",
+ stanza:top_tag());
+ return;
+ end
+ else
+ log("debug", "store hint detected");
+ if orig_type == 'error' then
+ log("debug", "Not archiving stanza: %s (type)", stanza:top_tag());
+ return;
+ end
end
-- or if hints suggest we shouldn't
if stanza:get_child("no-permanent-storage", "urn:xmpp:hints") -- The XEP needs to decide on "store" or "storage"
--
2.11.0

@ -0,0 +1,24 @@
From: Andreas Granig <agranig@sipwise.com>
Date: Wed Aug 7 22:34:34 2013 +0200
Subject: sipwise custom auth
---
--- a/plugins/mod_auth_sql.lua
+++ b/plugins/mod_auth_sql.lua
@@ -71,7 +71,7 @@ local function getsql(sql, ...)
end
local function get_password(username)
- local stmt, err = getsql("SELECT `password` FROM `authreg` WHERE `username`=? AND `realm`=?", username, module.host);
+ local stmt, err = getsql("SELECT `password` FROM `subscriber` WHERE `username`=? AND `domain`=?", username, module.host);
if stmt then
for row in stmt:rows(true) do
return row.password;
@@ -109,7 +109,7 @@ function provider.get_sasl_handler()
end
function provider.users()
- local stmt, err = getsql("SELECT `username` FROM `authreg` WHERE `realm`=?", module.host);
+ local stmt, err = getsql("SELECT `username` FROM `subscriber` WHERE `domain`=?", module.host);
if stmt then
local next, state = stmt:rows(true)
return function()

@ -0,0 +1,6 @@
mod_auth_sql.path
0001-TT-7482-mod_man-support-mam-version-0.5-urn-xmpp-mam.patch
0002-TT-8297-mam-implement-archive-to-DB.patch
0003-TT-9303-mod_mam-sipwise_archive.lib-fix-crash-at-fin.patch
0004-TT-9311-mod_mam-sipwise_archive.lib-full-username.patch
0005-TT-9317-mod_mam-don-t-store-bodyless-chat-messages.patch

2
debian/rules vendored

@ -3,4 +3,4 @@
# export DH_VERBOSE=1
%:
dh $@
dh $@ --with quilt

@ -8,7 +8,7 @@ local new_sasl = require "util.sasl".new;
local DBI = require "DBI"
local connection;
local params = module:get_option("auth_sql", module:get_option("auth_sql"));
local params = module:get_option("auth_sql", module:get_option("sql"));
local resolve_relative_path = require "core.configmanager".resolve_relative_path;
@ -43,18 +43,17 @@ end
do -- process options to get a db connection
params = params or { driver = "SQLite3" };
if params.driver == "SQLite3" then
params.database = resolve_relative_path(prosody.paths.data or ".", params.database or "prosody.sqlite");
end
assert(params.driver and params.database, "Both the SQL driver and the database need to be specified");
assert(connect());
end
local function getsql(sql, ...)
module:log("debug", "getsql: %s", sql);
if params.driver == "PostgreSQL" then
sql = sql:gsub("`", "\"");
end
@ -67,21 +66,20 @@ local function getsql(sql, ...)
local ok, err = stmt:execute(...);
if not ok and not test_connection() then error("connection failed"); end
if not ok then return nil, err; end
return stmt;
end
local function get_password(username)
local substmt, err;
substmt, err = getsql("SELECT `password` FROM `subscriber` WHERE `username`=? AND `domain`=?", username, module.host);
if substmt then
for row in substmt:rows(true) do
module:log("debug", "get_password: found subscriber %s@%s", username, module.host);
local stmt, err = getsql("SELECT `password` FROM `authreg` WHERE `username`=? AND `realm`=?", username, module.host);
if stmt then
for row in stmt:rows(true) do
return row.password;
end
end
end
provider = {};
function provider.test_password(username, password)
@ -111,7 +109,7 @@ function provider.get_sasl_handler()
end
function provider.users()
local stmt, err = getsql("SELECT `username` FROM `subscriber` WHERE `domain`=?", module.host);
local stmt, err = getsql("SELECT `username` FROM `authreg` WHERE `realm`=?", module.host);
if stmt then
local next, state = stmt:rows(true)
return function()

@ -4,6 +4,7 @@
-- This file is MIT/X11 licensed.
local st = require"util.stanza";
local xmlns_mam = "urn:xmpp:mam:0";
local default_attrs = {
always = true, [true] = "always",
@ -11,7 +12,7 @@ local default_attrs = {
roster = "roster",
}
local function tostanza(prefs, xmlns_mam)
local function tostanza(prefs)
local default = prefs[false];
default = default_attrs[default];
local prefstanza = st.stanza("prefs", { xmlns = xmlns_mam, default = default });

@ -3,8 +3,7 @@
--
-- This file is MIT/X11 licensed.
local xmlns_mam0 = "urn:xmpp:mam:0";
local xmlns_mam1 = "urn:xmpp:mam:1";
local xmlns_mam = "urn:xmpp:mam:0";
local xmlns_delay = "urn:xmpp:delay";
local xmlns_forward = "urn:xmpp:forward:0";
@ -37,15 +36,29 @@ if global_default_policy ~= "roster" then
global_default_policy = module:get_option_boolean("default_archive_policy", global_default_policy);
end
local archive = module:require "sipwise_archive";
local archive_store = "archive2";
local archive = assert(module:open_store(archive_store, "archive"));
if archive.name == "null" or not archive.find then
if not archive.find then
module:log("debug", "Attempt to open archive storage returned a valid driver but it does not seem to implement the storage API");
module:log("debug", "mod_%s does not support archiving", archive._provided_by or archive.name and "storage_"..archive.name.."(?)" or "<unknown>");
else
module:log("debug", "Attempt to open archive storage returned null driver");
end
module:log("debug", "See https://prosody.im/doc/storage and https://prosody.im/doc/archiving for more information");
module:log("info", "Using in-memory fallback archive driver");
archive = module:require "fallback_archive";
end
local cleanup;
-- Handle prefs.
local function handle_prefs(event, xmlns_mam)
module:hook("iq/self/"..xmlns_mam..":prefs", function(event)
local origin, stanza = event.origin, event.stanza;
local user = origin.username;
if stanza.attr.type == "get" then
local prefs = prefs_to_stanza(get_prefs(user), xmlns_mam);
local prefs = prefs_to_stanza(get_prefs(user));
local reply = st.reply(stanza):add_child(prefs);
origin.send(reply);
else -- type == "set"
@ -59,47 +72,24 @@ local function handle_prefs(event, xmlns_mam)
end
end
return true;
end
module:hook("iq/self/"..xmlns_mam1..":prefs", function(event)
return handle_prefs(event, xmlns_mam1)
end);
module:hook("iq/self/"..xmlns_mam0..":prefs", function(event)
return handle_prefs(event, xmlns_mam0)
end);
local query_form = {}
query_form[xmlns_mam1] = dataform {
{ name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam1; };
{ name = "with"; type = "jid-single"; };
{ name = "start"; type = "text-single" };
{ name = "end"; type = "text-single"; };
};
query_form[xmlns_mam0] = dataform {
{ name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam0; };
local query_form = dataform {
{ name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam; };
{ name = "with"; type = "jid-single"; };
{ name = "start"; type = "text-single" };
{ name = "end"; type = "text-single"; };
};
-- Serve form
local function get_form(event, xmlns_mam)
module:hook("iq-get/self/"..xmlns_mam..":query", function(event)
local origin, stanza = event.origin, event.stanza;
origin.send(st.reply(stanza):add_child(query_form[xmlns_mam]:form()));
origin.send(st.reply(stanza):add_child(query_form:form()));
return true;
end
module:hook("iq-get/self/"..xmlns_mam1..":query", function(event)
return get_form(event, xmlns_mam1);
end);
module:hook("iq-get/self/"..xmlns_mam0..":query", function(event)
return get_form(event, xmlns_mam0);
end);
-- Handle archive queries
local function handle_query(event, xmlns_mam)
module:hook("iq-set/self/"..xmlns_mam..":query", function(event)
local origin, stanza = event.origin, event.stanza;
local query = stanza.tags[1];
local qid = query.attr.queryid;
@ -111,7 +101,7 @@ local function handle_query(event, xmlns_mam)
local form = query:get_child("x", "jabber:x:data");
if form then
local err;
form, err = query_form[xmlns_mam]:data(form);
form, err = query_form:data(form);
if err then
origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err))));
return true;
@ -155,13 +145,9 @@ local function handle_query(event, xmlns_mam)
return true;
end
local total = tonumber(err);
local msg_reply_attr;
if xmlns_mam == xmlns_mam0 then
origin.send(st.reply(stanza));
msg_reply_attr = { to = stanza.attr.from, from = stanza.attr.to };
end
origin.send(st.reply(stanza));
local msg_reply_attr = { to = stanza.attr.from, from = stanza.attr.to };
local results = {};
@ -206,27 +192,11 @@ local function handle_query(event, xmlns_mam)
-- That's all folks!
module:log("debug", "Archive query %s completed", tostring(qid));
local reply_stanza;
if xmlns_mam == xmlns_mam0 then
reply_stanza = st.message(msg_reply_attr);
else
reply_stanza = st.reply(stanza);
end
if form or xmlns_mam == xmlns_mam0 then
reply_stanza:tag("fin",{ xmlns = xmlns_mam, queryid = qid, complete = complete })
:add_child(rsm.generate { first = first, last = last, count = total })
end
origin.send(reply_stanza);
origin.send(st.message(msg_reply_attr)
:tag("fin", { xmlns = xmlns_mam, queryid = qid, complete = complete })
:add_child(rsm.generate {
first = first, last = last, count = total }));
return true;
end
module:hook("iq-set/self/"..xmlns_mam1..":query", function(event)
return handle_query(event, xmlns_mam1);
end);
module:hook("iq-set/self/"..xmlns_mam0..":query", function(event)
return handle_query(event, xmlns_mam0);
end);
local function has_in_roster(user, who)
@ -267,25 +237,11 @@ local function message_handler(event, c2s)
local orig_from = stanza.attr.from;
local orig_to = stanza.attr.to or orig_from;
-- Stanza without 'to' are treated as if it was to their own bare jid
local body = stanza:get_child("body");
local force_store = stanza:get_child("store", "urn:xmpp:hints");
if not force_store then
-- We store chat messages or normal messages that have a body
if not(orig_type == "chat" or (orig_type == "normal" and body)) then
log("debug", "Not archiving stanza: %s (type)", stanza:top_tag());
return;
elseif (orig_type == 'chat' and not body) then
log("debug", "Not archiving stanza: %s (type), has no body",
stanza:top_tag());
return;
end
else
log("debug", "store hint detected");
if orig_type == 'error' then
log("debug", "Not archiving stanza: %s (type)", stanza:top_tag());
return;
end
-- We store chat messages or normal messages that have a body
if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body")) ) then
log("debug", "Not archiving stanza: %s (type)", stanza:top_tag());
return;
end
-- or if hints suggest we shouldn't
if stanza:get_child("no-permanent-storage", "urn:xmpp:hints") -- The XEP needs to decide on "store" or "storage"
@ -374,11 +330,9 @@ module:hook("pre-message/full", c2s_message_handler, 2);
module:hook("message/bare", message_handler, 2);
module:hook("message/full", message_handler, 2);
module:add_feature(xmlns_mam0); -- COMPAT with XEP-0313 v 0.1
module:add_feature(xmlns_mam1); -- COMPAT with XEP-0313 v 0.5
module:add_feature(xmlns_mam); -- COMPAT with XEP-0313 v 0.1
module:hook("account-disco-info", function(event)
(event.reply or event.stanza):tag("feature", {var=xmlns_mam0}):up();
(event.reply or event.stanza):tag("feature", {var=xmlns_mam1}):up();
(event.reply or event.stanza):tag("feature", {var=xmlns_mam}):up();
end);

@ -1,172 +0,0 @@
-- luacheck: ignore 212/self
local uuid = require "util.uuid".generate;
local archive_store = { _provided_by = "mam"; name = "fallback"; };
local serialize = require "util.serialization".serialize;
local deserialize = require "util.serialization".deserialize;
local st = require "util.stanza";
local mod_sql = module:require("sql");
local params = module:get_option("sql", {});
local engine = mod_sql:create_engine(params);
engine:execute("SET NAMES 'utf8' COLLATE 'utf8_bin';");
local log = require "util.logger".init("sipwise_archive");
local ut_tostring = require "util.table".table.tostring;
local host = module.host;
local store_query=[[
INSERT INTO `sipwise_mam` (`username`, `key`, `stanza`, `epoch`, `with`)
VALUES (?,UuidToBin(?),?,?,?);
]]
local delete_query=[[
DELETE FROM `sipwise_mam`
WHERE `username` = ?;
]]
local delete_query_extra=[[
DELETE FROM `sipwise_mam`
WHERE `username` = ? AND `epoch` <= ?;
]]
local select_key_query=[[
SELECT `id` FROM `sipwise_mam`
WHERE `key` = UuidToBin(?);
]]
local select_query_base=[[
SELECT UuidFromBin(`key`),`stanza`,`epoch`,`with` FROM `sipwise_mam`
WHERE `username` = ?
]]
-- Reconnect to DB if necessary
local function reconect_check()
if not engine.conn:ping() then
engine.conn = nil;
log("debug", "DDBB reconecting");
engine:connect();
end
end
local function load_db(query, _params)
local res;
reconect_check();
log("debug", "query[%s]", query);
log("debug", "_params[%s]", ut_tostring(_params));
res = engine:select(query, unpack(_params));
local out = {};
for row in res do
table.insert(out, {row[1], row[2], row[3], row[4]});
end
return out;
end
local function key_get_id(key)
local res;
reconect_check();
-- key is an uuid
if string.len(key) ~= 36 then
log("warn", "key[%s] is not a proper uuid");
return nil;
end
res = engine:select(select_key_query, key);
local out = {};
for row in res do
table.insert(out, row[1]);
end
return out[1];
end
local function key_in_db(key)
local res = key_get_id(key);
if res then
return true;
else
return false;
end
end
function archive_store:append(username, key, value, when, with)
reconect_check();
if not key or key_in_db(key) then
key = uuid();
end
engine:insert(store_query, username..'@'..host, key, serialize(st.preserialize(value)),
when, with);
engine.conn:commit();
end
function archive_store:find(username, query)
local qstart, qend, qwith = -math.huge, math.huge;
local qlimit, qid;
local db_query = select_query_base;
local _params = { username..'@'..host, };
local i, values = 0;
if query then
if query.reverse then
if query.before then
qid = key_get_id(query.before);
end
elseif query.after then
qid = key_get_id(query.after);
end
qwith = query.with;
qlimit = query.limit;
qstart = query.start or qstart;
qend = query["end"] or qend;
end
if qwith then
db_query = db_query.." AND `with` = ?";
table.insert(_params, qwith);
end
if qid then
if query.reverse then
db_query = db_query.." AND `id` < ?";
else
db_query = db_query.." AND `id` > ?";
end
table.insert(_params, qid);
end
db_query = db_query.." AND (`epoch` >= ? AND `epoch` <= ?)";
table.insert(_params, qstart);
table.insert(_params, qend);
db_query = db_query.." ORDER BY `epoch`";
if query.reverse then
db_query = db_query.." DESC";
end
if qlimit then
db_query = db_query.." LIMIT ?";
table.insert(_params, qlimit);
end
db_query = db_query..";"
values = load_db(db_query, _params);
return function ()
i = i + 1;
if values[i] then
return values[i][1], deserialize(values[i][2]), values[i][3], values[i][4];
end
end
end
function archive_store:delete(username, query)
local jid = username..'@'..host
if not query or next(query) == nil then
-- no specifics, delete everything
reconect_check();
engine:delete(delete_query, jid);
engine.conn:commit();
return true;
end
local qend = query["end"] or math.huge;
reconect_check();
engine:delete(delete_query_extra, jid, qend);
engine.conn:commit();
return true;
end
return archive_store;
Loading…
Cancel
Save