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