aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeny Khramtsov <ekhramtsov@process-one.net>2018-11-23 13:33:29 +0300
committerEvgeny Khramtsov <ekhramtsov@process-one.net>2018-11-23 13:33:29 +0300
commit1cdca1ab99c8a0dfd7cab8a760a65840067bea16 (patch)
tree8eb0355d134894d01b9b8df23c8286b0d1e7d9af /src
parentMerge pull request #2690 from nosnilmot/stopping-hook (diff)
Support for XEP-0411: Bookmarks Conversion
Diffstat (limited to 'src')
-rw-r--r--src/jd2ejd.erl3
-rw-r--r--src/mod_admin_extra.erl4
-rw-r--r--src/mod_private.erl132
-rw-r--r--src/mod_pubsub.erl2
-rw-r--r--src/prosody2ejabberd.erl4
5 files changed, 104 insertions, 41 deletions
diff --git a/src/jd2ejd.erl b/src/jd2ejd.erl
index 35ebeab8d..394a5a471 100644
--- a/src/jd2ejd.erl
+++ b/src/jd2ejd.erl
@@ -111,7 +111,6 @@ process_xdb(User, Server,
xdb_data(_User, _Server, {xmlcdata, _CData}) -> ok;
xdb_data(User, Server, #xmlel{attrs = Attrs} = El) ->
From = jid:make(User, Server),
- LUser = From#jid.luser,
LServer = From#jid.lserver,
case fxml:get_attr_s(<<"xmlns">>, Attrs) of
?NS_AUTH ->
@@ -142,7 +141,7 @@ xdb_data(User, Server, #xmlel{attrs = Attrs} = El) ->
(_) -> true
end, Attrs),
catch mod_private:set_data(
- LUser, LServer,
+ From,
[{XMLNS, El#xmlel{attrs = NewAttrs}}]);
_ ->
?DEBUG("jd2ejd: Unknown namespace \"~s\"~n", [XMLNS])
diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl
index 5db82f82a..62e07f9e9 100644
--- a/src/mod_admin_extra.erl
+++ b/src/mod_admin_extra.erl
@@ -1388,8 +1388,8 @@ private_set(Username, Host, ElementString) ->
private_set2(Username, Host, Xml) ->
NS = fxml:get_tag_attr_s(<<"xmlns">>, Xml),
- mod_private:set_data(jid:nodeprep(Username), jid:nameprep(Host),
- [{NS, Xml}]).
+ JID = jid:make(Username, Host),
+ mod_private:set_data(JID, [{NS, Xml}]).
%%%
%%% Shared Roster Groups
diff --git a/src/mod_private.erl b/src/mod_private.erl
index f6a57c63c..7d139080a 100644
--- a/src/mod_private.erl
+++ b/src/mod_private.erl
@@ -28,13 +28,14 @@
-author('alexey@process-one.net').
-protocol({xep, 49, '1.2'}).
+-protocol({xep, 411, '0.2.0'}).
-behaviour(gen_mod).
-export([start/2, stop/1, reload/3, process_sm_iq/1, import_info/0,
remove_user/2, get_data/2, get_data/3, export/1,
- import/5, import_start/2, mod_opt_type/1, set_data/3,
- mod_options/1, depends/2]).
+ import/5, import_start/2, mod_opt_type/1, set_data/2,
+ mod_options/1, depends/2, get_sm_features/5, pubsub_publish_item/6]).
-include("logger.hrl").
-include("xmpp.hrl").
@@ -57,16 +58,16 @@ start(Host, Opts) ->
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
Mod:init(Host, Opts),
init_cache(Mod, Host, Opts),
- ejabberd_hooks:add(remove_user, Host, ?MODULE,
- remove_user, 50),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
- ?NS_PRIVATE, ?MODULE, process_sm_iq).
+ ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50),
+ ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
+ ejabberd_hooks:add(pubsub_publish_item, Host, ?MODULE, pubsub_publish_item, 50),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE, ?MODULE, process_sm_iq).
stop(Host) ->
- ejabberd_hooks:delete(remove_user, Host, ?MODULE,
- remove_user, 50),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
- ?NS_PRIVATE).
+ ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50),
+ ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
+ ejabberd_hooks:delete(pubsub_publish_item, Host, ?MODULE, pubsub_publish_item, 50),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE).
reload(Host, NewOpts, OldOpts) ->
NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE),
@@ -78,9 +79,41 @@ reload(Host, NewOpts, OldOpts) ->
end,
init_cache(NewMod, Host, NewOpts).
+depends(_Host, _Opts) ->
+ [{mod_pubsub, soft}].
+
+mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
+mod_opt_type(O) when O == cache_life_time; O == cache_size ->
+ fun (I) when is_integer(I), I > 0 -> I;
+ (infinity) -> infinity
+ end;
+mod_opt_type(O) when O == use_cache; O == cache_missed ->
+ fun (B) when is_boolean(B) -> B end.
+
+mod_options(Host) ->
+ [{db_type, ejabberd_config:default_db(Host, ?MODULE)},
+ {use_cache, ejabberd_config:use_cache(Host)},
+ {cache_size, ejabberd_config:cache_size(Host)},
+ {cache_missed, ejabberd_config:cache_missed(Host)},
+ {cache_life_time, ejabberd_config:cache_life_time(Host)}].
+
+-spec get_sm_features({error, stanza_error()} | empty | {result, [binary()]},
+ jid(), jid(), binary(), binary()) ->
+ {error, stanza_error()} | empty | {result, [binary()]}.
+get_sm_features({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
+ Acc;
+get_sm_features(Acc, _From, _To, <<"">>, _Lang) ->
+ {result, [?NS_BOOKMARKS_CONVERSION_0 |
+ case Acc of
+ {result, Features} -> Features;
+ empty -> []
+ end]};
+get_sm_features(Acc, _From, _To, _Node, _Lang) ->
+ Acc.
+
-spec process_sm_iq(iq()) -> iq().
process_sm_iq(#iq{type = Type, lang = Lang,
- from = #jid{luser = LUser, lserver = LServer},
+ from = #jid{luser = LUser, lserver = LServer} = From,
to = #jid{luser = LUser, lserver = LServer},
sub_els = [#private{sub_els = Els0}]} = IQ) ->
case filter_xmlels(Els0) of
@@ -88,9 +121,11 @@ process_sm_iq(#iq{type = Type, lang = Lang,
Txt = <<"No private data found in this query">>,
xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
Data when Type == set ->
- case set_data(LUser, LServer, Data) of
+ case set_data(From, Data) of
ok ->
xmpp:make_iq_result(IQ);
+ {error, #stanza_error{} = Err} ->
+ xmpp:make_error(IQ, Err);
{error, _} ->
Txt = <<"Database failure">>,
Err = xmpp:err_internal_server_error(Txt, Lang),
@@ -120,12 +155,21 @@ filter_xmlels(Els) ->
end
end, Els).
--spec set_data(binary(), binary(), [{binary(), xmlel()}]) -> ok | {error, _}.
-set_data(LUser, LServer, Data) ->
+-spec set_data(jid(), [{binary(), xmlel()}]) -> ok | {error, _}.
+set_data(JID, Data) ->
+ set_data(JID, Data, true).
+
+-spec set_data(jid(), [{binary(), xmlel()}], boolean()) -> ok | {error, _}.
+set_data(JID, Data, Publish) ->
+ {LUser, LServer, _} = jid:tolower(JID),
Mod = gen_mod:db_mod(LServer, ?MODULE),
case Mod:set_data(LUser, LServer, Data) of
ok ->
- delete_cache(Mod, LUser, LServer, Data);
+ delete_cache(Mod, LUser, LServer, Data),
+ case Publish of
+ true -> publish_data(JID, Data);
+ false -> ok
+ end;
{error, _} = Err ->
Err
end.
@@ -181,6 +225,43 @@ remove_user(User, Server) ->
Mod:del_data(LUser, LServer),
delete_cache(Mod, LUser, LServer, Data).
+%%%===================================================================
+%%% Pubsub
+%%%===================================================================
+-spec publish_data(jid(), [{binary(), xmlel()}]) -> ok | {error, stanza_error()}.
+publish_data(JID, Data) ->
+ {_, LServer, _} = LBJID = jid:remove_resource(jid:tolower(JID)),
+ case gen_mod:is_loaded(LServer, mod_pubsub) of
+ true ->
+ case lists:keyfind(?NS_STORAGE_BOOKMARKS, 1, Data) of
+ false -> ok;
+ {_, El} ->
+ PubOpts = [{persist_items, true},
+ {access_model, whitelist}],
+ case mod_pubsub:publish_item(
+ LBJID, LServer, ?NS_STORAGE_BOOKMARKS, JID,
+ <<>>, [El], PubOpts, all) of
+ {result, _} -> ok;
+ {error, _} = Err -> Err
+ end
+ end;
+ false ->
+ ok
+ end.
+
+-spec pubsub_publish_item(binary(), binary(), jid(), jid(),
+ binary(), [xmlel()]) -> any().
+pubsub_publish_item(LServer, ?NS_STORAGE_BOOKMARKS,
+ #jid{luser = LUser, lserver = LServer} = From,
+ #jid{luser = LUser, lserver = LServer},
+ _ItemId, [Payload|_]) ->
+ set_data(From, [{?NS_STORAGE_BOOKMARKS, Payload}], false);
+pubsub_publish_item(_, _, _, _, _, _) ->
+ ok.
+
+%%%===================================================================
+%%% Cache
+%%%===================================================================
-spec delete_cache(module(), binary(), binary(), [{binary(), xmlel()}]) -> ok.
delete_cache(Mod, LUser, LServer, Data) ->
case use_cache(Mod, LServer) of
@@ -230,6 +311,9 @@ cache_nodes(Mod, Host) ->
false -> ejabberd_cluster:get_nodes()
end.
+%%%===================================================================
+%%% Import/Export
+%%%===================================================================
import_info() ->
[{<<"private_storage">>, 4}].
@@ -244,21 +328,3 @@ export(LServer) ->
import(LServer, {sql, _}, DBType, Tab, L) ->
Mod = gen_mod:db_mod(DBType, ?MODULE),
Mod:import(LServer, Tab, L).
-
-depends(_Host, _Opts) ->
- [].
-
-mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
-mod_opt_type(O) when O == cache_life_time; O == cache_size ->
- fun (I) when is_integer(I), I > 0 -> I;
- (infinity) -> infinity
- end;
-mod_opt_type(O) when O == use_cache; O == cache_missed ->
- fun (B) when is_boolean(B) -> B end.
-
-mod_options(Host) ->
- [{db_type, ejabberd_config:default_db(Host, ?MODULE)},
- {use_cache, ejabberd_config:use_cache(Host)},
- {cache_size, ejabberd_config:cache_size(Host)},
- {cache_missed, ejabberd_config:cache_missed(Host)},
- {cache_life_time, ejabberd_config:cache_life_time(Host)}].
diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl
index 2609beb86..3367c192e 100644
--- a/src/mod_pubsub.erl
+++ b/src/mod_pubsub.erl
@@ -65,7 +65,7 @@
%% exports for console debug manual use
-export([create_node/5, create_node/7, delete_node/3,
- subscribe_node/5, unsubscribe_node/5, publish_item/6,
+ subscribe_node/5, unsubscribe_node/5, publish_item/6, publish_item/8,
delete_item/4, delete_item/5, send_items/7, get_items/2, get_item/3,
get_cached_item/2, get_configure/5, set_configure/5,
tree_action/3, node_action/4, node_call/4]).
diff --git a/src/prosody2ejabberd.erl b/src/prosody2ejabberd.erl
index b95faad51..b8d9f4da1 100644
--- a/src/prosody2ejabberd.erl
+++ b/src/prosody2ejabberd.erl
@@ -169,8 +169,6 @@ convert_data(Host, "roster", User, [Data]) ->
end, Data),
lists:foreach(fun mod_roster:set_roster/1, Rosters);
convert_data(Host, "private", User, [Data]) ->
- LUser = jid:nodeprep(User),
- LServer = jid:nameprep(Host),
PrivData = lists:flatmap(
fun({_TagXMLNS, Raw}) ->
case deserialize(Raw) of
@@ -181,7 +179,7 @@ convert_data(Host, "private", User, [Data]) ->
[]
end
end, Data),
- mod_private:set_data(LUser, LServer, PrivData);
+ mod_private:set_data(jid:make(User, Host), PrivData);
convert_data(Host, "vcard", User, [Data]) ->
LServer = jid:nameprep(Host),
case deserialize(Data) of