aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2012-04-12 14:22:56 +1000
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2012-04-12 14:22:56 +1000
commit86435ba9aa55dcfb84d80da4afb88ab138ce957c (patch)
tree4bc3e52a57e4a33f78d30cd92294aeb655000a45 /src
parentParse and encode https header names like native http parser does (diff)
ODBC support for mod_blocking
Diffstat (limited to 'src')
-rw-r--r--src/mod_blocking_odbc.erl365
-rw-r--r--src/mod_privacy_odbc.erl14
-rw-r--r--src/odbc/odbc_queries.erl12
3 files changed, 391 insertions, 0 deletions
diff --git a/src/mod_blocking_odbc.erl b/src/mod_blocking_odbc.erl
new file mode 100644
index 000000000..016e7945e
--- /dev/null
+++ b/src/mod_blocking_odbc.erl
@@ -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.
diff --git a/src/mod_privacy_odbc.erl b/src/mod_privacy_odbc.erl
index 432617ebe..87303b57a 100644
--- a/src/mod_privacy_odbc.erl
+++ b/src/mod_privacy_odbc.erl
@@ -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),
diff --git a/src/odbc/odbc_queries.erl b/src/odbc/odbc_queries.erl
index 2af5f2ba6..3ec3b1be5 100644
--- a/src/odbc/odbc_queries.erl
+++ b/src/odbc/odbc_queries.erl
@@ -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, "'"]).