./ct_report/coverage/mod_privacy.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% File : mod_privacy.erl
3 %%% Author : Alexey Shchepin <alexey@process-one.net>
4 %%% Purpose : jabber:iq:privacy support
5 %%% Created : 21 Jul 2003 by Alexey Shchepin <alexey@process-one.net>
6 %%%
7 %%%
8 %%% ejabberd, Copyright (C) 2002-2011 ProcessOne
9 %%%
10 %%% This program is free software; you can redistribute it and/or
11 %%% modify it under the terms of the GNU General Public License as
12 %%% published by the Free Software Foundation; either version 2 of the
13 %%% License, or (at your option) any later version.
14 %%%
15 %%% This program is distributed in the hope that it will be useful,
16 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
17 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 %%% General Public License for more details.
19 %%%
20 %%% You should have received a copy of the GNU General Public License
21 %%% along with this program; if not, write to the Free Software
22 %%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 %%%
24 %%%----------------------------------------------------------------------
25
26 -module(mod_privacy).
27 -author('alexey@process-one.net').
28 -xep([{xep, 16}, {version, "1.6"}]).
29 -xep([{xep, 126}, {version, "1.1"}]).
30 -behaviour(gen_mod).
31 -behaviour(mongoose_module_metrics).
32
33 %% gen_mod
34 -export([start/2]).
35 -export([stop/1]).
36 -export([supported_features/0]).
37 -export([config_spec/0]).
38
39 -export([process_iq_set/4,
40 process_iq_get/5,
41 get_user_list/3,
42 check_packet/5,
43 remove_user/3,
44 remove_domain/3,
45 updated_list/3,
46 disco_local_features/1,
47 remove_unused_backend_opts/1
48 ]).
49
50 -export([config_metrics/1]).
51
52 -ignore_xref([
53 behaviour_info/1, check_packet/5, get_user_list/3, process_iq_get/5,
54 process_iq_set/4, remove_user/3, updated_list/3,
55 remove_user/3, remove_domain/3, disco_local_features/1]).
56
57 -include("jlib.hrl").
58 -include("mod_privacy.hrl").
59 -include("mongoose_config_spec.hrl").
60
61 -export_type([list_name/0]).
62 -export_type([list_item/0]).
63 -export_type([privacy_item_type/0]).
64
65 -type list_name() :: binary() | none.
66 -type list_item() :: #listitem{}.
67 -type privacy_item_type() :: none | jid | group | subscription.
68
69 %% ------------------------------------------------------------------
70 %% gen_mod callbacks
71 %% ------------------------------------------------------------------
72
73 -spec start(mongooseim:host_type(), gen_mod:module_opts()) -> ok.
74 start(HostType, Opts) when is_map(Opts) ->
75 5 mod_privacy_backend:init(HostType, Opts),
76 5 ejabberd_hooks:add(hooks(HostType)).
77
78 -spec stop(mongooseim:host_type()) -> ok.
79 stop(HostType) ->
80 5 ejabberd_hooks:delete(hooks(HostType)).
81
82 config_spec() ->
83 332 #section{
84 items = #{<<"backend">> => #option{type = atom,
85 validate = {module, mod_privacy}},
86 <<"riak">> => riak_config_spec()},
87 defaults = #{<<"backend">> => mnesia},
88 process = fun ?MODULE:remove_unused_backend_opts/1
89 }.
90
91 riak_config_spec() ->
92 332 #section{
93 items = #{<<"defaults_bucket_type">> => #option{type = binary,
94 validate = non_empty},
95 <<"names_bucket_type">> => #option{type = binary,
96 validate = non_empty},
97 <<"bucket_type">> => #option{type = binary,
98 validate = non_empty}
99 },
100 defaults = #{<<"defaults_bucket_type">> => <<"privacy_defaults">>,
101 <<"names_bucket_type">> => <<"privacy_lists_names">>,
102 <<"bucket_type">> => <<"privacy_lists">>},
103 include = always
104 }.
105
106
:-(
remove_unused_backend_opts(Opts = #{backend := riak}) -> Opts;
107
:-(
remove_unused_backend_opts(Opts) -> maps:remove(riak, Opts).
108
109 -spec supported_features() -> [atom()].
110 supported_features() ->
111
:-(
[dynamic_domains].
112
113 hooks(HostType) ->
114 10 [
115 {disco_local_features, HostType, ?MODULE, disco_local_features, 98},
116 {privacy_iq_get, HostType, ?MODULE, process_iq_get, 50},
117 {privacy_iq_set, HostType, ?MODULE, process_iq_set, 50},
118 {privacy_get_user_list, HostType, ?MODULE, get_user_list, 50},
119 {privacy_check_packet, HostType, ?MODULE, check_packet, 50},
120 {privacy_updated_list, HostType, ?MODULE, updated_list, 50},
121 {remove_user, HostType, ?MODULE, remove_user, 50},
122 {remove_domain, HostType, ?MODULE, remove_domain, 50},
123 {anonymous_purge_hook, HostType, ?MODULE, remove_user, 50}
124 ].
125
126 %% ------------------------------------------------------------------
127 %% Handlers
128 %% ------------------------------------------------------------------
129
130 -spec disco_local_features(mongoose_disco:feature_acc()) -> mongoose_disco:feature_acc().
131 disco_local_features(Acc = #{node := <<>>}) ->
132 3 mongoose_disco:add_features([?NS_PRIVACY], Acc);
133 disco_local_features(Acc) ->
134 1 Acc.
135
136 process_iq_get(Acc,
137 _From = #jid{luser = LUser, lserver = LServer},
138 _To,
139 #iq{xmlns = ?NS_PRIVACY, sub_el = #xmlel{children = Els}},
140 #userlist{name = Active}) ->
141 54 HostType = mongoose_acc:host_type(Acc),
142 54 Res = case xml:remove_cdata(Els) of
143 [] ->
144 3 process_lists_get(HostType, LUser, LServer, Active);
145 [#xmlel{name = Name, attrs = Attrs}] ->
146 50 case Name of
147 <<"list">> ->
148 50 ListName = xml:get_attr(<<"name">>, Attrs),
149 50 process_list_get(HostType, LUser, LServer, ListName);
150 _ ->
151
:-(
{error, mongoose_xmpp_errors:bad_request()}
152 end;
153 _ ->
154 1 {error, mongoose_xmpp_errors:bad_request()}
155 end,
156 54 mongoose_acc:set(hook, result, Res, Acc);
157 process_iq_get(Val, _, _, _, _) ->
158 8 Val.
159
160 process_lists_get(HostType, LUser, LServer, Active) ->
161 3 case mod_privacy_backend:get_list_names(HostType, LUser, LServer) of
162 {ok, {Default, ListNames}} ->
163 2 {result, [list_names_query(Active, Default, ListNames)]};
164 {error, not_found} ->
165 1 {result, [empty_list_names_query()]};
166 {error, _Reason} ->
167
:-(
{error, mongoose_xmpp_errors:internal_server_error()}
168 end.
169
170 process_list_get(HostType, LUser, LServer, {value, Name}) ->
171 50 case mod_privacy_backend:get_privacy_list(HostType, LUser, LServer, Name) of
172 {ok, List} ->
173 48 LItems = lists:map(fun item_to_xml/1, List),
174 48 {result, [list_query_result(Name, LItems)]};
175 {error, not_found} ->
176 2 {error, mongoose_xmpp_errors:item_not_found()};
177 {error, _Reason} ->
178
:-(
{error, mongoose_xmpp_errors:internal_server_error()}
179 end;
180 process_list_get(_HostType, _LUser, _LServer, false) ->
181
:-(
{error, mongoose_xmpp_errors:bad_request()}.
182
183 process_iq_set(Acc, From, _To, #iq{xmlns = ?NS_PRIVACY, sub_el = SubEl}) ->
184 111 #xmlel{children = Els} = SubEl,
185 111 HostType = mongoose_acc:host_type(Acc),
186 111 Res = case xml:remove_cdata(Els) of
187 [#xmlel{name = Name, attrs = Attrs, children = SubEls}] ->
188 111 ListName = xml:get_attr(<<"name">>, Attrs),
189 111 case Name of
190 <<"list">> ->
191 51 process_list_set(HostType, From, ListName,
192 xml:remove_cdata(SubEls));
193 <<"active">> ->
194 44 process_active_set(HostType, From, ListName);
195 <<"default">> ->
196 16 process_default_set(HostType, From, ListName);
197 _ ->
198
:-(
{error, mongoose_xmpp_errors:bad_request()}
199 end;
200 _ ->
201
:-(
{error, mongoose_xmpp_errors:bad_request()}
202 end,
203 111 mongoose_acc:set(hook, result, Res, Acc);
204 process_iq_set(Val, _, _, _) ->
205 28 Val.
206
207 process_default_set(HostType, #jid{luser = LUser, lserver = LServer}, {value, Name}) ->
208 15 case mod_privacy_backend:set_default_list(HostType, LUser, LServer, Name) of
209 ok ->
210 14 {result, []};
211 {error, not_found} ->
212 1 {error, mongoose_xmpp_errors:item_not_found()};
213 {error, _Reason} ->
214
:-(
{error, mongoose_xmpp_errors:internal_server_error()}
215 end;
216 process_default_set(HostType, #jid{luser = LUser, lserver = LServer}, false) ->
217 1 case mod_privacy_backend:forget_default_list(HostType, LUser, LServer) of
218 ok ->
219 1 {result, []};
220 {error, _Reason} ->
221
:-(
{error, mongoose_xmpp_errors:internal_server_error()}
222 end.
223
224 process_active_set(HostType, #jid{luser = LUser, lserver = LServer}, {value, Name}) ->
225 43 case mod_privacy_backend:get_privacy_list(HostType, LUser, LServer, Name) of
226 {ok, List} ->
227 42 NeedDb = is_list_needdb(List),
228 42 {result, [], #userlist{name = Name, list = List, needdb = NeedDb}};
229 {error, not_found} ->
230 1 {error, mongoose_xmpp_errors:item_not_found()};
231 {error, _Reason} ->
232
:-(
{error, mongoose_xmpp_errors:internal_server_error()}
233 end;
234 process_active_set(_HostType, _UserJID, false) ->
235 1 {result, [], #userlist{}}.
236
237 process_list_set(HostType, UserJID, {value, Name}, Els) ->
238 51 case parse_items(Els) of
239 false ->
240
:-(
{error, mongoose_xmpp_errors:bad_request()};
241 remove ->
242 1 remove_privacy_list(HostType, UserJID, Name);
243 List ->
244 50 replace_privacy_list(HostType, UserJID, Name, List)
245 end;
246 process_list_set(_HostType, _UserJID, false, _Els) ->
247
:-(
{error, mongoose_xmpp_errors:bad_request()}.
248
249 remove_privacy_list(HostType, #jid{luser = LUser, lserver = LServer} = UserJID, Name) ->
250 1 case mod_privacy_backend:remove_privacy_list(HostType, LUser, LServer, Name) of
251 ok ->
252 1 UserList = #userlist{name = Name, list = []},
253 1 broadcast_privacy_list(UserJID, Name, UserList),
254 1 {result, []};
255 %% TODO if Name == Active -> conflict
256 {error, conflict} ->
257
:-(
{error, mongoose_xmpp_errors:conflict()};
258 {error, _Reason} ->
259
:-(
{error, mongoose_xmpp_errors:internal_server_error()}
260 end.
261
262 replace_privacy_list(HostType, #jid{luser = LUser, lserver = LServer} = UserJID, Name, List) ->
263 50 case mod_privacy_backend:replace_privacy_list(HostType, LUser, LServer, Name, List) of
264 ok ->
265 50 NeedDb = is_list_needdb(List),
266 50 UserList = #userlist{name = Name, list = List, needdb = NeedDb},
267 50 broadcast_privacy_list(UserJID, Name, UserList),
268 50 {result, []};
269 {error, _Reason} ->
270
:-(
{error, mongoose_xmpp_errors:internal_server_error()}
271 end.
272
273 is_list_needdb(Items) ->
274 113 lists:any(fun is_item_needdb/1, Items).
275
276 12 is_item_needdb(#listitem{type = subscription}) -> true;
277 2 is_item_needdb(#listitem{type = group}) -> true;
278 101 is_item_needdb(_) -> false.
279
280 get_user_list(_, HostType, #jid{luser = LUser, lserver = LServer}) ->
281 502 case mod_privacy_backend:get_default_list(HostType, LUser, LServer) of
282 {ok, {Default, List}} ->
283 21 NeedDb = is_list_needdb(List),
284 21 #userlist{name = Default, list = List, needdb = NeedDb};
285 {error, _} ->
286 481 #userlist{}
287 end.
288
289 %% From is the sender, To is the destination.
290 %% If Dir = out, User@Server is the sender account (From).
291 %% If Dir = in, User@Server is the destination account (To).
292 check_packet(Acc, _JID, #userlist{list = []}, _, _Dir) ->
293 2441 mongoose_acc:set(hook, result, allow, Acc);
294 check_packet(Acc, JID,
295 #userlist{list = List, needdb = NeedDb},
296 {From, To, Name, Type}, Dir) ->
297 303 HostType = mongoose_acc:host_type(Acc),
298 303 PType = packet_directed_type(Dir, packet_type(Name, Type)),
299 303 LJID = case Dir of
300 195 in -> jid:to_lower(From);
301 108 out -> jid:to_lower(To)
302 end,
303 303 {Subscription, Groups} =
304 case NeedDb of
305 true ->
306 61 roster_get_jid_info(HostType, JID, LJID);
307 false ->
308 242 {[], []}
309 end,
310 303 CheckResult = check_packet_aux(List, PType, Type, LJID, Subscription, Groups),
311 303 mongoose_acc:set(hook, result, CheckResult, Acc).
312
313 %% allow error messages
314 check_packet_aux(_, message, <<"error">>, _JID, _Subscription, _Groups) ->
315 8 allow;
316 %% if we run of of list items then it is allowed
317 check_packet_aux([], _PType, _MType, _JID, _Subscription, _Groups) ->
318 225 allow;
319 %% check packet against next privacy list item
320 check_packet_aux([Item | List], PType, MType, JID, Subscription, Groups) ->
321 383 #listitem{type = Type, value = Value, action = Action} = Item,
322 383 do_check_packet_aux(Type, Action, PType, Value, JID, MType, Subscription, Groups, Item, List).
323
324 %% list set by blocking commands (XEP-0191) block all communication, both in and out,
325 %% for a given JID
326 do_check_packet_aux(jid, block, message, JID, JID, _, _, _, _, _) ->
327
:-(
block;
328 do_check_packet_aux(jid, block, message_out, JID, JID, _, _, _, _, _) ->
329 3 block;
330 %% then we do more complicated checking
331 do_check_packet_aux(Type, Action, PType, Value, JID, MType, Subscription, Groups, Item, List) ->
332 380 #listitem{type = Type, value = Value, action = Action} = Item,
333 380 case {is_ptype_match(Item, PType), Type} of
334 {true, none} ->
335 29 Action;
336 {true, _} ->
337 186 case is_type_match(Type, Value, JID, Subscription, Groups) of
338 true ->
339 38 Action;
340 false ->
341 148 check_packet_aux(List, PType, MType, JID, Subscription, Groups)
342 end;
343 {false, _} ->
344 165 check_packet_aux(List, PType, MType, JID, Subscription, Groups)
345 end.
346
347 is_ptype_match(#listitem{match_all = true}, _PType) ->
348 156 true;
349 is_ptype_match(Item, message) ->
350 41 Item#listitem.match_message;
351 is_ptype_match(_Item, message_out) ->
352 17 false; % according to xep-0016, privacy lists do not stop outgoing messages (so they say)
353 is_ptype_match(Item, iq) ->
354 75 Item#listitem.match_iq;
355 is_ptype_match(Item, presence_in) ->
356 12 Item#listitem.match_presence_in;
357 is_ptype_match(Item, presence_out) ->
358 63 Item#listitem.match_presence_out;
359 is_ptype_match(_Item, other) ->
360 16 false.
361
362 is_type_match(jid, Value, JID, _Subscription, _Groups) ->
363 173 case Value of
364 {<<>>, Server, <<>>} ->
365 7 case JID of
366 {_, Server, _} ->
367 7 true;
368 _ ->
369
:-(
false
370 end;
371 {User, Server, <<>>} ->
372 166 case JID of
373 {User, Server, _} ->
374 24 true;
375 _ ->
376 142 false
377 end;
378 _ ->
379
:-(
Value == JID
380 end;
381
382 is_type_match(subscription, Value, _JID, Subscription, _Groups) ->
383 12 Value == Subscription;
384 is_type_match(group, Value, _JID, _Subscription, Groups) ->
385 1 lists:member(Value, Groups).
386
387 remove_user(Acc, User, Server) ->
388 114 LUser = jid:nodeprep(User),
389 114 LServer = jid:nameprep(Server),
390 114 HostType = mongoose_acc:host_type(Acc),
391 114 R = mod_privacy_backend:remove_user(HostType, LUser, LServer),
392 114 mongoose_lib:log_if_backend_error(R, ?MODULE, ?LINE, {Acc, User, Server}),
393 114 Acc.
394
395 -spec remove_domain(mongoose_hooks:simple_acc(),
396 mongooseim:host_type(), jid:lserver()) ->
397 mongoose_hooks:simple_acc().
398 remove_domain(Acc, HostType, Domain) ->
399
:-(
mod_privacy_backend:remove_domain(HostType, Domain),
400
:-(
Acc.
401
402 1 updated_list(_, #userlist{name = SameName}, #userlist{name = SameName} = New) -> New;
403 52 updated_list(_, Old, _) -> Old.
404
405 %% ------------------------------------------------------------------
406 %% Deserialization
407 %% ------------------------------------------------------------------
408
409 16 packet_directed_type(out, message) -> message_out;
410 58 packet_directed_type(in, message) -> message;
411 116 packet_directed_type(in, iq) -> iq;
412 17 packet_directed_type(in, presence) -> presence_in;
413 88 packet_directed_type(out, presence) -> presence_out;
414 8 packet_directed_type(_Dir, _Type) -> other.
415
416 74 packet_type(<<"message">>, _Type) -> message;
417 116 packet_type(<<"iq">>, _Type) -> iq;
418 packet_type(<<"presence">>, Type) ->
419 113 case Type of
420 %% notification
421 28 undefined -> presence;
422 77 <<"unavailable">> -> presence;
423 %% subscribe, subscribed, unsubscribe,
424 %% unsubscribed, error, probe, or other
425 8 _ -> other
426 end.
427
428 parse_items([]) ->
429 1 remove;
430 parse_items(Els) ->
431 50 parse_items(Els, []).
432
433 parse_items([], Res) ->
434 %% Sort the items by their 'order' attribute
435 50 lists:keysort(#listitem.order, Res);
436 parse_items([#xmlel{name = <<"item">>, attrs = Attrs,
437 children = SubEls} | Els], Res) ->
438 57 Type = xml:get_attr_s(<<"type">>, Attrs),
439 57 Value = xml:get_attr_s(<<"value">>, Attrs),
440 57 SAction = xml:get_attr_s(<<"action">>, Attrs),
441 57 SOrder = xml:get_attr_s(<<"order">>, Attrs),
442 57 Action = parse_action(SAction),
443 57 Order = parse_order(SOrder),
444 57 I1 = set_action_and_order(Action, Order),
445 57 I2 = set_type_and_value(Type, Value, I1),
446 57 I3 = set_matches(SubEls, I2),
447 57 parse_items(Els, add_item(I3, Res));
448 parse_items(_, _Res) ->
449
:-(
false.
450
451 parse_action(<<>>) ->
452
:-(
false;
453 parse_action(Action) ->
454 57 binary_to_action_s(Action).
455
456 parse_order(<<>>) ->
457
:-(
false;
458 parse_order(Order) ->
459 57 validate_order(binary_to_order_s(Order)).
460
461 validate_order(Order) when Order >= 0 ->
462 57 Order;
463 validate_order(_) ->
464
:-(
false.
465
466 set_action_and_order(false, _) ->
467
:-(
false;
468 set_action_and_order(_, false) ->
469
:-(
false;
470 set_action_and_order(Action, Order) when is_atom(Action), is_integer(Order) ->
471 57 #listitem{action = Action, order = Order}.
472
473 set_type_and_value(_Type, _Value, false) ->
474
:-(
false;
475 set_type_and_value(<<>>, _Value, Item) ->
476 29 Item;
477 set_type_and_value(_Type, <<>>, _Item) ->
478
:-(
false;
479 set_type_and_value(<<"jid">>, Value, Item) ->
480 19 case jid:from_binary(Value) of
481 error ->
482
:-(
false;
483 JID ->
484 19 Item#listitem{type = jid, value = jid:to_lower(JID)}
485 end;
486 set_type_and_value(<<"group">>, Value, Item) ->
487 1 Item#listitem{type = group, value = Value};
488 set_type_and_value(<<"subscription">>, Value, Item) ->
489 8 case Value of
490 <<"none">> ->
491 2 Item#listitem{type = subscription, value = none};
492 <<"both">> ->
493 2 Item#listitem{type = subscription, value = both};
494 <<"from">> ->
495 2 Item#listitem{type = subscription, value = from};
496 <<"to">> ->
497 2 Item#listitem{type = subscription, value = to};
498 _ ->
499
:-(
false
500 end.
501
502 set_matches(_SubEls, false) ->
503
:-(
false;
504 set_matches(SubEls, Item) ->
505 57 parse_matches(Item, xml:remove_cdata(SubEls)).
506
507 parse_matches(Item, []) ->
508 12 Item#listitem{match_all = true};
509 parse_matches(Item, Els) ->
510 45 parse_matches1(Item, Els).
511
512 parse_matches1(Item, []) ->
513 45 Item;
514 parse_matches1(Item, [#xmlel{name = <<"message">>} | Els]) ->
515 37 parse_matches1(Item#listitem{match_message = true}, Els);
516 parse_matches1(Item, [#xmlel{name = <<"iq">>} | Els]) ->
517 1 parse_matches1(Item#listitem{match_iq = true}, Els);
518 parse_matches1(Item, [#xmlel{name = <<"presence-in">>} | Els]) ->
519 1 parse_matches1(Item#listitem{match_presence_in = true}, Els);
520 parse_matches1(Item, [#xmlel{name = <<"presence-out">>} | Els]) ->
521 6 parse_matches1(Item#listitem{match_presence_out = true}, Els);
522 parse_matches1(_Item, [#xmlel{} | _Els]) ->
523
:-(
false.
524
525 add_item(false, Items) ->
526
:-(
Items;
527 add_item(Item, Items) ->
528 57 [Item | Items].
529
530 %% ------------------------------------------------------------------
531 %% Serialization
532 %% ------------------------------------------------------------------
533
534 empty_list_names_query() ->
535 1 #xmlel{
536 name = <<"query">>,
537 attrs = [{<<"xmlns">>, ?NS_PRIVACY}]}.
538
539 list_names_query(Active, Default, ListNames) ->
540 2 #xmlel{
541 name = <<"query">>,
542 attrs = [{<<"xmlns">>, ?NS_PRIVACY}],
543 children = list_names(Active, Default, ListNames)}.
544
545 list_names(Active, Default, ListNames) ->
546 2 [list_name(<<"active">>, Active) || Active =/= none] ++
547 1 [list_name(<<"default">>, Default) || Default =/= none] ++
548 3 [list_name(<<"list">>, ListName) || ListName <- ListNames].
549
550 list_name(Type, Name) ->
551 5 #xmlel{name = Type, attrs = [{<<"name">>, Name}]}.
552
553 list_query_result(Name, LItems) ->
554 48 #xmlel{
555 name = <<"query">>,
556 attrs = [{<<"xmlns">>, ?NS_PRIVACY}],
557 children = [
558 #xmlel{
559 name = <<"list">>,
560 attrs = [{<<"name">>, Name}],
561 children = LItems}]}.
562
563 item_to_xml(Item) ->
564 55 #xmlel{
565 name = <<"item">>,
566 attrs = item_to_xml_attrs(Item),
567 children = item_to_xml_children(Item)}.
568
569 item_to_xml_attrs(Item=#listitem{type=none}) ->
570 29 item_to_xml_attrs1(Item);
571 item_to_xml_attrs(Item=#listitem{type=Type, value=Value}) ->
572 26 [{<<"type">>, type_to_binary(Type)},
573 {<<"value">>, value_to_binary(Type, Value)}
574 | item_to_xml_attrs1(Item)].
575
576 item_to_xml_attrs1(#listitem{action=Action, order=Order}) ->
577 55 [{<<"action">>, action_to_binary(Action)},
578 {<<"order">>, order_to_binary(Order)}].
579
580 item_to_xml_children(#listitem{match_all=true}) ->
581 10 [];
582 item_to_xml_children(#listitem{match_all=false,
583 match_iq=MatchIQ,
584 match_message=MatchMessage,
585 match_presence_in=MatchPresenceIn,
586 match_presence_out=MatchPresenceOut}) ->
587 37 [#xmlel{name = <<"message">>} || MatchMessage]
588 45 ++ [#xmlel{name = <<"presence-in">>} || MatchPresenceIn]
589 6 ++ [#xmlel{name = <<"presence-out">>} || MatchPresenceOut]
590 1 ++ [#xmlel{name = <<"iq">>} || MatchIQ].
591
592 action_to_binary(Action) ->
593 55 case Action of
594 5 allow -> <<"allow">>;
595 50 deny -> <<"deny">>
596 end.
597
598 order_to_binary(Order) ->
599 55 integer_to_binary(Order).
600
601 binary_to_order(Binary) ->
602 57 binary_to_integer(Binary).
603
604 type_to_binary(Type) ->
605 26 case Type of
606 17 jid -> <<"jid">>;
607 1 group -> <<"group">>;
608 8 subscription -> <<"subscription">>
609 end.
610
611 value_to_binary(Type, Val) ->
612 26 case Type of
613 17 jid -> jid:to_binary(Val);
614 1 group -> Val;
615 subscription ->
616 8 case Val of
617 2 both -> <<"both">>;
618 2 to -> <<"to">>;
619 2 from -> <<"from">>;
620 2 none -> <<"none">>
621 end
622 end.
623
624 binary_to_action(S) ->
625 57 case S of
626 5 <<"allow">> -> allow;
627 52 <<"deny">> -> deny
628 end.
629
630 binary_to_action_s(Action) ->
631 57 try
632 57 binary_to_action(Action)
633 catch error:_ ->
634
:-(
false
635 end.
636
637 binary_to_order_s(Order) ->
638 57 try
639 57 binary_to_order(Order)
640 catch error:_ ->
641
:-(
false
642 end.
643
644 %% ------------------------------------------------------------------
645 %% Ejabberd
646 %% ------------------------------------------------------------------
647
648 broadcast_privacy_list(UserJID, Name, UserList) ->
649 51 JID = jid:to_bare(UserJID),
650 51 ejabberd_sm:route(JID, JID, broadcast_privacy_list_packet(Name, UserList)).
651
652 %% TODO this is dirty
653 broadcast_privacy_list_packet(Name, UserList) ->
654 51 {broadcast, {privacy_list, UserList, Name}}.
655
656 roster_get_jid_info(HostType, ToJID, LJID) ->
657 61 mongoose_hooks:roster_get_jid_info(HostType, ToJID, LJID).
658
659 -spec config_metrics(mongooseim:host_type()) -> [{gen_mod:opt_key(), gen_mod:opt_value()}].
660 config_metrics(HostType) ->
661 12 mongoose_module_metrics:opts_for_module(HostType, ?MODULE, [backend]).
Line Hits Source