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