mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
ODBC support for mod_blocking
This commit is contained in:
parent
e2d6bc95a4
commit
86435ba9aa
@ -68,6 +68,7 @@
|
||||
\newcommand{\modannounce}{\module{mod\_announce}}
|
||||
\newcommand{\modannounceodbc}{\module{mod\_announce\_odbc}}
|
||||
\newcommand{\modblocking}{\module{mod\_blocking}}
|
||||
\newcommand{\modblockingodbc}{\module{mod\_blocking\_odbc}}
|
||||
\newcommand{\modcaps}{\module{mod\_caps}}
|
||||
\newcommand{\modconfigure}{\module{mod\_configure}}
|
||||
\newcommand{\moddisco}{\module{mod\_disco}}
|
||||
@ -2586,6 +2587,7 @@ The following table lists all modules included in \ejabberd{}.
|
||||
\hline \ahrefloc{modannounce}{\modannounceodbc{}} & Manage announcements & recommends \modadhoc{} \\
|
||||
& & supported DB (*) \\
|
||||
\hline \modblocking{} & Simple Communications Blocking (\xepref{0191}) & \modprivacy{} \\
|
||||
\hline \modblockingodbc{} & Simple Communications Blocking (\xepref{0191}) & \modprivacyodbc{} \\
|
||||
\hline \modcaps{} & Entity Capabilities (\xepref{0115}) & \\
|
||||
\hline \modconfigure{} & Server configuration using Ad-Hoc & \modadhoc{} \\
|
||||
\hline \ahrefloc{moddisco}{\moddisco{}} & Service Discovery (\xepref{0030}) & \\
|
||||
@ -2664,6 +2666,7 @@ database for the following data:
|
||||
\item vCard-Based Avatars: Use \term{mod\_vcard\_xupdate\_odbc} instead of \term{mod\_vcard\_xupdate}.
|
||||
\item Private XML storage: Use \term{mod\_private\_odbc} instead of \term{mod\_private}.
|
||||
\item User rules for blocking communications: Use \term{mod\_privacy\_odbc} instead of \term{mod\_privacy}.
|
||||
\item Simple Communications Blocking: Use \term{mod\_blocking\_odbc} instead of \term{mod\_blocking}.
|
||||
\item Pub-Sub nodes, items and subscriptions: Use \term{mod\_pubsub\_odbc} instead of \term{mod\_pubsub}.
|
||||
\item Multi-user chats: Use \term{mod\_muc\_odbc} instead of \term{mod\_muc}.
|
||||
\item Manage announcements: Use \term{mod\_announce\_odbc} instead of \term{mod\_announce}.
|
||||
|
365
src/mod_blocking_odbc.erl
Normal file
365
src/mod_blocking_odbc.erl
Normal file
@ -0,0 +1,365 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : mod_blocking_odbc.erl
|
||||
%%% Author : Stephan Maka
|
||||
%%% Purpose : XEP-0191: Simple Communications Blocking
|
||||
%%% Created : 24 Aug 2008 by Stephan Maka <stephan@spaceboyz.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2012 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
%%% published by the Free Software Foundation; either version 2 of the
|
||||
%%% License, or (at your option) any later version.
|
||||
%%%
|
||||
%%% This program is distributed in the hope that it will be useful,
|
||||
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
%%% General Public License for more details.
|
||||
%%%
|
||||
%%% You should have received a copy of the GNU General Public License
|
||||
%%% along with this program; if not, write to the Free Software
|
||||
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
%%% 02111-1307 USA
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(mod_blocking_odbc).
|
||||
|
||||
-behaviour(gen_mod).
|
||||
|
||||
-export([start/2, stop/1,
|
||||
process_iq/3,
|
||||
process_iq_set/4,
|
||||
process_iq_get/5]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
-include("mod_privacy.hrl").
|
||||
|
||||
start(Host, Opts) ->
|
||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||
ejabberd_hooks:add(privacy_iq_get, Host,
|
||||
?MODULE, process_iq_get, 40),
|
||||
ejabberd_hooks:add(privacy_iq_set, Host,
|
||||
?MODULE, process_iq_set, 40),
|
||||
mod_disco:register_feature(Host, ?NS_BLOCKING),
|
||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING,
|
||||
?MODULE, process_iq, IQDisc).
|
||||
|
||||
stop(Host) ->
|
||||
ejabberd_hooks:delete(privacy_iq_get, Host,
|
||||
?MODULE, process_iq_get, 40),
|
||||
ejabberd_hooks:delete(privacy_iq_set, Host,
|
||||
?MODULE, process_iq_set, 40),
|
||||
mod_disco:unregister_feature(Host, ?NS_BLOCKING),
|
||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING).
|
||||
|
||||
process_iq(_From, _To, IQ) ->
|
||||
SubEl = IQ#iq.sub_el,
|
||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}.
|
||||
|
||||
process_iq_get(_, From, _To,
|
||||
#iq{xmlns = ?NS_BLOCKING,
|
||||
sub_el = {xmlelement, "blocklist", _, _}},
|
||||
_) ->
|
||||
#jid{luser = LUser, lserver = LServer} = From,
|
||||
{stop, process_blocklist_get(LUser, LServer)};
|
||||
|
||||
process_iq_get(Acc, _, _, _, _) ->
|
||||
Acc.
|
||||
|
||||
process_iq_set(_, From, _To, #iq{xmlns = ?NS_BLOCKING,
|
||||
sub_el = {xmlelement, SubElName, _, SubEls}}) ->
|
||||
#jid{luser = LUser, lserver = LServer} = From,
|
||||
Res =
|
||||
case {SubElName, xml:remove_cdata(SubEls)} of
|
||||
{"block", []} ->
|
||||
{error, ?ERR_BAD_REQUEST};
|
||||
{"block", Els} ->
|
||||
JIDs = parse_blocklist_items(Els, []),
|
||||
process_blocklist_block(LUser, LServer, JIDs);
|
||||
{"unblock", []} ->
|
||||
process_blocklist_unblock_all(LUser, LServer);
|
||||
{"unblock", Els} ->
|
||||
JIDs = parse_blocklist_items(Els, []),
|
||||
process_blocklist_unblock(LUser, LServer, JIDs);
|
||||
_ ->
|
||||
{error, ?ERR_BAD_REQUEST}
|
||||
end,
|
||||
{stop, Res};
|
||||
|
||||
process_iq_set(Acc, _, _, _) ->
|
||||
Acc.
|
||||
|
||||
is_list_needdb(Items) ->
|
||||
lists:any(
|
||||
fun(X) ->
|
||||
case X#listitem.type of
|
||||
subscription -> true;
|
||||
group -> true;
|
||||
_ -> false
|
||||
end
|
||||
end, Items).
|
||||
|
||||
list_to_blocklist_jids([], JIDs) ->
|
||||
JIDs;
|
||||
|
||||
list_to_blocklist_jids([#listitem{type = jid,
|
||||
action = deny,
|
||||
value = JID} = Item | Items], JIDs) ->
|
||||
case Item of
|
||||
#listitem{match_all = true} ->
|
||||
Match = true;
|
||||
#listitem{match_iq = true,
|
||||
match_message = true,
|
||||
match_presence_in = true,
|
||||
match_presence_out = true} ->
|
||||
Match = true;
|
||||
_ ->
|
||||
Match = false
|
||||
end,
|
||||
if
|
||||
Match ->
|
||||
list_to_blocklist_jids(Items, [JID | JIDs]);
|
||||
true ->
|
||||
list_to_blocklist_jids(Items, JIDs)
|
||||
end;
|
||||
|
||||
% Skip Privacy List items than cannot be mapped to Blocking items
|
||||
list_to_blocklist_jids([_ | Items], JIDs) ->
|
||||
list_to_blocklist_jids(Items, JIDs).
|
||||
|
||||
parse_blocklist_items([], JIDs) ->
|
||||
JIDs;
|
||||
|
||||
parse_blocklist_items([{xmlelement, "item", Attrs, _} | Els], JIDs) ->
|
||||
case xml:get_attr("jid", Attrs) of
|
||||
{value, JID1} ->
|
||||
JID = jlib:jid_tolower(jlib:string_to_jid(JID1)),
|
||||
parse_blocklist_items(Els, [JID | JIDs]);
|
||||
false ->
|
||||
% Tolerate missing jid attribute
|
||||
parse_blocklist_items(Els, JIDs)
|
||||
end;
|
||||
|
||||
parse_blocklist_items([_ | Els], JIDs) ->
|
||||
% Tolerate unknown elements
|
||||
parse_blocklist_items(Els, JIDs).
|
||||
|
||||
process_blocklist_block(LUser, LServer, JIDs) ->
|
||||
F = fun() ->
|
||||
Default =
|
||||
case mod_privacy_odbc:sql_get_default_privacy_list_t(LUser) of
|
||||
{selected, ["name"], []} ->
|
||||
Name = "Blocked contacts",
|
||||
mod_privacy_odbc:sql_add_privacy_list(LUser, Name),
|
||||
mod_privacy_odbc:sql_set_default_privacy_list(
|
||||
LUser, Name),
|
||||
Name;
|
||||
{selected, ["name"], [{Name}]} ->
|
||||
Name
|
||||
end,
|
||||
{selected, ["id"], [{ID}]} =
|
||||
mod_privacy_odbc:sql_get_privacy_list_id_t(LUser, Default),
|
||||
case mod_privacy_odbc:sql_get_privacy_list_data_by_id_t(ID) of
|
||||
{selected,
|
||||
["t", "value", "action", "ord",
|
||||
"match_all", "match_iq", "match_message",
|
||||
"match_presence_in",
|
||||
"match_presence_out"],
|
||||
RItems = [_|_]} ->
|
||||
List = lists:map(
|
||||
fun mod_privacy_odbc:raw_to_item/1,
|
||||
RItems);
|
||||
_ ->
|
||||
List = []
|
||||
end,
|
||||
AlreadyBlocked = list_to_blocklist_jids(List, []),
|
||||
NewList =
|
||||
lists:foldr(
|
||||
fun(JID, List1) ->
|
||||
case lists:member(JID, AlreadyBlocked) of
|
||||
true ->
|
||||
List1;
|
||||
false ->
|
||||
[#listitem{type = jid,
|
||||
value = JID,
|
||||
action = deny,
|
||||
order = 0,
|
||||
match_all = true
|
||||
} | List1]
|
||||
end
|
||||
end, List, JIDs),
|
||||
NewRItems = lists:map(
|
||||
fun mod_privacy_odbc:item_to_raw/1,
|
||||
NewList),
|
||||
mod_privacy_odbc:sql_set_privacy_list(
|
||||
ID, NewRItems),
|
||||
{ok, Default, NewList}
|
||||
end,
|
||||
case ejabberd_odbc:sql_transaction(LServer, F) of
|
||||
{atomic, {error, _} = Error} ->
|
||||
Error;
|
||||
{atomic, {ok, Default, List}} ->
|
||||
UserList = make_userlist(Default, List),
|
||||
broadcast_list_update(LUser, LServer, Default, UserList),
|
||||
broadcast_blocklist_event(LUser, LServer, {block, JIDs}),
|
||||
{result, [], UserList};
|
||||
_ ->
|
||||
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||
end.
|
||||
|
||||
process_blocklist_unblock_all(LUser, LServer) ->
|
||||
F = fun() ->
|
||||
case mod_privacy_odbc:sql_get_default_privacy_list_t(LUser) of
|
||||
{selected, ["name"], []} ->
|
||||
ok;
|
||||
{selected, ["name"], [{Default}]} ->
|
||||
{selected, ["id"], [{ID}]} =
|
||||
mod_privacy_odbc:sql_get_privacy_list_id_t(
|
||||
LUser, Default),
|
||||
case mod_privacy_odbc:sql_get_privacy_list_data_by_id_t(ID) of
|
||||
{selected,
|
||||
["t", "value", "action", "ord",
|
||||
"match_all", "match_iq", "match_message",
|
||||
"match_presence_in",
|
||||
"match_presence_out"],
|
||||
RItems = [_|_]} ->
|
||||
List = lists:map(
|
||||
fun mod_privacy_odbc:raw_to_item/1,
|
||||
RItems),
|
||||
NewList =
|
||||
lists:filter(
|
||||
fun(#listitem{action = A}) ->
|
||||
A =/= deny
|
||||
end, List),
|
||||
NewRItems = lists:map(
|
||||
fun mod_privacy_odbc:item_to_raw/1,
|
||||
NewList),
|
||||
mod_privacy_odbc:sql_set_privacy_list(
|
||||
ID, NewRItems),
|
||||
{ok, Default, NewList};
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
_ ->
|
||||
ok
|
||||
end
|
||||
end,
|
||||
case ejabberd_odbc:sql_transaction(LServer, F) of
|
||||
{atomic, {error, _} = Error} ->
|
||||
Error;
|
||||
{atomic, ok} ->
|
||||
{result, []};
|
||||
{atomic, {ok, Default, List}} ->
|
||||
UserList = make_userlist(Default, List),
|
||||
broadcast_list_update(LUser, LServer, Default, UserList),
|
||||
broadcast_blocklist_event(LUser, LServer, unblock_all),
|
||||
{result, [], UserList};
|
||||
_ ->
|
||||
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||
end.
|
||||
|
||||
process_blocklist_unblock(LUser, LServer, JIDs) ->
|
||||
F = fun() ->
|
||||
case mod_privacy_odbc:sql_get_default_privacy_list_t(LUser) of
|
||||
{selected, ["name"], []} ->
|
||||
ok;
|
||||
{selected, ["name"], [{Default}]} ->
|
||||
{selected, ["id"], [{ID}]} =
|
||||
mod_privacy_odbc:sql_get_privacy_list_id_t(
|
||||
LUser, Default),
|
||||
case mod_privacy_odbc:sql_get_privacy_list_data_by_id_t(ID) of
|
||||
{selected,
|
||||
["t", "value", "action", "ord",
|
||||
"match_all", "match_iq", "match_message",
|
||||
"match_presence_in",
|
||||
"match_presence_out"],
|
||||
RItems = [_|_]} ->
|
||||
List = lists:map(
|
||||
fun mod_privacy_odbc:raw_to_item/1,
|
||||
RItems),
|
||||
NewList =
|
||||
lists:filter(
|
||||
fun(#listitem{action = deny,
|
||||
type = jid,
|
||||
value = JID}) ->
|
||||
not(lists:member(JID, JIDs));
|
||||
(_) ->
|
||||
true
|
||||
end, List),
|
||||
NewRItems = lists:map(
|
||||
fun mod_privacy_odbc:item_to_raw/1,
|
||||
NewList),
|
||||
mod_privacy_odbc:sql_set_privacy_list(
|
||||
ID, NewRItems),
|
||||
{ok, Default, NewList};
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
_ ->
|
||||
ok
|
||||
end
|
||||
end,
|
||||
case ejabberd_odbc:sql_transaction(LServer, F) of
|
||||
{atomic, {error, _} = Error} ->
|
||||
Error;
|
||||
{atomic, ok} ->
|
||||
{result, []};
|
||||
{atomic, {ok, Default, List}} ->
|
||||
UserList = make_userlist(Default, List),
|
||||
broadcast_list_update(LUser, LServer, Default, UserList),
|
||||
broadcast_blocklist_event(LUser, LServer, {unblock, JIDs}),
|
||||
{result, [], UserList};
|
||||
_ ->
|
||||
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||
end.
|
||||
|
||||
make_userlist(Name, List) ->
|
||||
NeedDb = is_list_needdb(List),
|
||||
#userlist{name = Name, list = List, needdb = NeedDb}.
|
||||
|
||||
broadcast_list_update(LUser, LServer, Name, UserList) ->
|
||||
ejabberd_router:route(
|
||||
jlib:make_jid(LUser, LServer, ""),
|
||||
jlib:make_jid(LUser, LServer, ""),
|
||||
{xmlelement, "broadcast", [],
|
||||
[{privacy_list, UserList, Name}]}).
|
||||
|
||||
broadcast_blocklist_event(LUser, LServer, Event) ->
|
||||
JID = jlib:make_jid(LUser, LServer, ""),
|
||||
ejabberd_router:route(
|
||||
JID, JID,
|
||||
{xmlelement, "broadcast", [],
|
||||
[{blocking, Event}]}).
|
||||
|
||||
process_blocklist_get(LUser, LServer) ->
|
||||
case catch mod_privacy_odbc:sql_get_default_privacy_list(LUser, LServer) of
|
||||
{selected, ["name"], []} ->
|
||||
{result, [{xmlelement, "blocklist",
|
||||
[{"xmlns", ?NS_BLOCKING}], []}]};
|
||||
{selected, ["name"], [{Default}]} ->
|
||||
case catch mod_privacy_odbc:sql_get_privacy_list_data(
|
||||
LUser, LServer, Default) of
|
||||
{selected, ["t", "value", "action", "ord", "match_all",
|
||||
"match_iq", "match_message",
|
||||
"match_presence_in", "match_presence_out"],
|
||||
RItems} ->
|
||||
List = lists:map(fun mod_privacy_odbc:raw_to_item/1, RItems),
|
||||
JIDs = list_to_blocklist_jids(List, []),
|
||||
Items = lists:map(
|
||||
fun(JID) ->
|
||||
?DEBUG("JID: ~p",[JID]),
|
||||
{xmlelement, "item",
|
||||
[{"jid", jlib:jid_to_string(JID)}], []}
|
||||
end, JIDs),
|
||||
{result,
|
||||
[{xmlelement, "blocklist", [{"xmlns", ?NS_BLOCKING}],
|
||||
Items}]};
|
||||
{'EXIT', _} ->
|
||||
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||
end;
|
||||
{'EXIT', _} ->
|
||||
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||
end.
|
@ -37,8 +37,19 @@
|
||||
check_packet/6,
|
||||
remove_user/2,
|
||||
item_to_raw/1,
|
||||
raw_to_item/1,
|
||||
updated_list/3]).
|
||||
|
||||
%% For mod_blocking_odbc
|
||||
-export([sql_add_privacy_list/2,
|
||||
sql_get_default_privacy_list/2,
|
||||
sql_get_default_privacy_list_t/1,
|
||||
sql_get_privacy_list_data/3,
|
||||
sql_get_privacy_list_data_by_id_t/1,
|
||||
sql_get_privacy_list_id_t/2,
|
||||
sql_set_default_privacy_list/2,
|
||||
sql_set_privacy_list/2]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
-include("mod_privacy.hrl").
|
||||
@ -836,6 +847,9 @@ sql_get_privacy_list_data(LUser, LServer, Name) ->
|
||||
sql_get_privacy_list_data_by_id(ID, LServer) ->
|
||||
odbc_queries:get_privacy_list_data_by_id(LServer, ID).
|
||||
|
||||
sql_get_privacy_list_data_by_id_t(ID) ->
|
||||
odbc_queries:get_privacy_list_data_by_id_t(ID).
|
||||
|
||||
sql_set_default_privacy_list(LUser, Name) ->
|
||||
Username = ejabberd_odbc:escape(LUser),
|
||||
SName = ejabberd_odbc:escape(Name),
|
||||
|
@ -70,6 +70,7 @@
|
||||
get_privacy_list_id_t/2,
|
||||
get_privacy_list_data/3,
|
||||
get_privacy_list_data_by_id/2,
|
||||
get_privacy_list_data_by_id_t/1,
|
||||
set_default_privacy_list/2,
|
||||
unset_default_privacy_list/2,
|
||||
remove_privacy_list/2,
|
||||
@ -506,6 +507,13 @@ get_privacy_list_data_by_id(LServer, ID) ->
|
||||
"from privacy_list_data "
|
||||
"where id='", ID, "' order by ord;"]).
|
||||
|
||||
get_privacy_list_data_by_id_t(ID) ->
|
||||
ejabberd_odbc:sql_query_t(
|
||||
["select t, value, action, ord, match_all, match_iq, "
|
||||
"match_message, match_presence_in, match_presence_out "
|
||||
"from privacy_list_data "
|
||||
"where id='", ID, "' order by ord;"]).
|
||||
|
||||
set_default_privacy_list(Username, SName) ->
|
||||
update_t("privacy_default_list", ["username", "name"],
|
||||
[Username, SName], ["username='", Username, "'"]).
|
||||
@ -834,6 +842,10 @@ get_privacy_list_data_by_id(LServer, ID) ->
|
||||
LServer,
|
||||
["EXECUTE dbo.get_privacy_list_data_by_id '", ID, "'"]).
|
||||
|
||||
get_privacy_list_data_by_id_t(ID) ->
|
||||
ejabberd_odbc:sql_query_t(
|
||||
["EXECUTE dbo.get_privacy_list_data_by_id '", ID, "'"]).
|
||||
|
||||
set_default_privacy_list(Username, SName) ->
|
||||
ejabberd_odbc:sql_query_t(
|
||||
["EXECUTE dbo.set_default_privacy_list '", Username, "' , '", SName, "'"]).
|
||||
|
Loading…
Reference in New Issue
Block a user