From 14f050331afee17d30f1c42f9b419837bde3eff8 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Sun, 2 Feb 2003 19:49:19 +0000 Subject: [PATCH] *** empty log message *** SVN Revision: 56 --- TODO | 2 + src/ejabberd.cfg | 2 + src/ejabberd_config.erl | 87 ++++++++--------- src/jd2ejd.erl | 204 ++++++++++++++++++++++++++++++++++++++++ src/mod_private.erl | 2 +- src/mod_roster.erl | 74 +++++++++++++++ 6 files changed, 327 insertions(+), 44 deletions(-) create mode 100644 src/jd2ejd.erl diff --git a/TODO b/TODO index a87f73c34..6d2ba9e30 100644 --- a/TODO +++ b/TODO @@ -9,3 +9,5 @@ SRV DNS records karma SSL JEP-62,63 (?) +make roster set work in one transaction + diff --git a/src/ejabberd.cfg b/src/ejabberd.cfg index 8724fea6a..6cc428f35 100644 --- a/src/ejabberd.cfg +++ b/src/ejabberd.cfg @@ -1,5 +1,7 @@ % $Id$ +override_acls. + {acl, admin, {user, "aleksey"}}. {acl, admin, {user, "ermine"}}. {acl, admin, {user, "test"}}. diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 321c735cb..16dc95602 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -50,17 +50,18 @@ load_file(File) -> process_term(Term, State) -> case Term of override_global -> - #state{override_global = true}; + State#state{override_global = true}; override_local -> - #state{override_local = true}; + State#state{override_local = true}; override_acls -> - #state{override_acls = true}; + State#state{override_acls = true}; {acl, ACLName, ACLData} -> - #state{opts = + State#state{opts = [acl:to_record(ACLName, ACLData) | State#state.opts]}; {access, RuleName, Rules} -> - #state{opts = [#config{key = {access, RuleName}, value = Rules} | - State#state.opts]}; + State#state{opts = [#config{key = {access, RuleName}, + value = Rules} | + State#state.opts]}; {Opt, Val} -> add_option(Opt, Val, State) end. @@ -74,49 +75,49 @@ add_option(Opt, Val, State) -> end, case Table of config -> - #state{opts = [#config{key = Opt, value = Val} | - State#state.opts]}; + State#state{opts = [#config{key = Opt, value = Val} | + State#state.opts]}; local_config -> - #state{opts = [#local_config{key = Opt, value = Val} | - State#state.opts]} + State#state{opts = [#local_config{key = Opt, value = Val} | + State#state.opts]} end. set_opts(State) -> Opts = lists:reverse(State#state.opts), - mnesia:transaction( - fun() -> - if - State#state.override_global -> - Ksg = mnesia:all_keys(config), - lists:foreach(fun(K) -> - mnesia:delete({config, K}) - end, Ksg); - true -> - ok - end, - if - State#state.override_local -> - Ksl = mnesia:all_keys(local_config), - lists:foreach(fun(K) -> - mnesia:delete({local_config, K}) - end, Ksl); - true -> - ok - end, - if - State#state.override_acls -> - Ksa = mnesia:all_keys(acl), - lists:foreach(fun(K) -> - mnesia:delete({acl, K}) - end, Ksa); - true -> - ok - end, - lists:foreach(fun(R) -> - mnesia:write(R) - end, Opts) - end). + F = fun() -> + if + State#state.override_global -> + Ksg = mnesia:all_keys(config), + lists:foreach(fun(K) -> + mnesia:delete({config, K}) + end, Ksg); + true -> + ok + end, + if + State#state.override_local -> + Ksl = mnesia:all_keys(local_config), + lists:foreach(fun(K) -> + mnesia:delete({local_config, K}) + end, Ksl); + true -> + ok + end, + if + State#state.override_acls -> + Ksa = mnesia:all_keys(acl), + lists:foreach(fun(K) -> + mnesia:delete({acl, K}) + end, Ksa); + true -> + ok + end, + lists:foreach(fun(R) -> + mnesia:write(R) + end, Opts) + end, + {atomic, _} = mnesia:transaction(F). add_global_option(Opt, Val) -> diff --git a/src/jd2ejd.erl b/src/jd2ejd.erl new file mode 100644 index 000000000..16ce514aa --- /dev/null +++ b/src/jd2ejd.erl @@ -0,0 +1,204 @@ +%%%---------------------------------------------------------------------- +%%% File : jd2ejd.erl +%%% Author : Alexey Shchepin +%%% Purpose : Import of jabberd1.4 user spool file +%%% Created : 2 Feb 2003 by Alexey Shchepin +%%% Id : $Id$ +%%%---------------------------------------------------------------------- + +-module(jd2ejd). +-author('alexey@sevcom.net'). +-vsn('$Revision$ '). + +-behaviour(gen_fsm). + +%% External exports +-export([start/1, start/2, receiver/2]). + +%% gen_fsm callbacks +-export([init/1, + wait_for_xdb/2, + xdb_data/2, + handle_event/3, + handle_sync_event/4, + code_change/4, + handle_info/3, + terminate/3]). + +-include("ejabberd.hrl"). +-include("namespaces.hrl"). + +-record(state, {socket, receiver, + user = "", server = ?MYNAME, resource = "" + }). + +%-define(DBGFSM, true). + +-ifdef(DBGFSM). +-define(FSMOPTS, [{debug, [trace]}]). +-else. +-define(FSMOPTS, []). +-endif. + + +%%%---------------------------------------------------------------------- +%%% API +%%%---------------------------------------------------------------------- +start(File) -> + User = filename:rootname(filename:basename(File)), + start(File, User). + +start(File, User) -> + gen_fsm:start(?MODULE, [File, User], ?FSMOPTS). + +%%%---------------------------------------------------------------------- +%%% Callback functions from gen_fsm +%%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Func: init/1 +%% Returns: {ok, StateName, StateData} | +%% {ok, StateName, StateData, Timeout} | +%% ignore | +%% {stop, StopReason} +%%---------------------------------------------------------------------- +init([File, User]) -> + %ReceiverPid = spawn(?MODULE, receiver, [Socket, self()]), + XMLStreamPid = xml_stream:start(self()), + {ok, Text} = file:read_file(File), + xml_stream:send_text(XMLStreamPid, Text), + {ok, wait_for_xdb, #state{user = User}}. + +%%---------------------------------------------------------------------- +%% Func: StateName/2 +%% Returns: {next_state, NextStateName, NextStateData} | +%% {next_state, NextStateName, NextStateData, Timeout} | +%% {stop, Reason, NewStateData} +%%---------------------------------------------------------------------- + +wait_for_xdb({xmlstreamstart, Name, Attrs}, StateData) -> + case Name of + "xdb" -> + {next_state, xdb_data, StateData}; + _ -> + {stop, normal, StateData} + end; + +wait_for_xdb(closed, StateData) -> + {stop, normal, StateData}. + + +xdb_data({xmlstreamelement, El}, StateData) -> + {xmlelement, Name, Attrs, Els} = El, + Server = StateData#state.server, + From = {StateData#state.user, + Server, + ""}, + NewState = + case xml:get_attr_s("xmlns", Attrs) of + ?NS_AUTH -> + Password = xml:get_tag_cdata(El), + ejabberd_auth:set_password(StateData#state.user, Password), + StateData; + ?NS_ROSTER -> + %mod_roster:process_iq(From, + % {"", ?MYNAME, ""}, + % {iq, "", set, ?NS_ROSTER, El}), + mod_roster:set_items(StateData#state.user, El), + StateData; + %?NS_REGISTER -> + % mod_register:process_iq( + % {"", "", ""}, {"", ?MYNAME, ""}, + % {iq, "", set, ?NS_REGISTER, El}), + % User = xml:get_path_s(El, [{elem, "username"}, cdata]), + % io:format("user ~s~n", [User]), + % StateData; + XMLNS -> + io:format("Unknown namespace \"~s\"~n", [XMLNS]), + StateData + end, + {next_state, xdb_data, NewState}; + +xdb_data({xmlstreamend, Name}, StateData) -> + {stop, normal, StateData}; + +xdb_data(closed, StateData) -> + % TODO + {stop, normal, StateData}. + + + +%%---------------------------------------------------------------------- +%% Func: StateName/3 +%% Returns: {next_state, NextStateName, NextStateData} | +%% {next_state, NextStateName, NextStateData, Timeout} | +%% {reply, Reply, NextStateName, NextStateData} | +%% {reply, Reply, NextStateName, NextStateData, Timeout} | +%% {stop, Reason, NewStateData} | +%% {stop, Reason, Reply, NewStateData} +%%---------------------------------------------------------------------- +%state_name(Event, From, StateData) -> +% Reply = ok, +% {reply, Reply, state_name, StateData}. + +%%---------------------------------------------------------------------- +%% Func: handle_event/3 +%% Returns: {next_state, NextStateName, NextStateData} | +%% {next_state, NextStateName, NextStateData, Timeout} | +%% {stop, Reason, NewStateData} +%%---------------------------------------------------------------------- +handle_event(Event, StateName, StateData) -> + {next_state, StateName, StateData}. + +%%---------------------------------------------------------------------- +%% Func: handle_sync_event/4 +%% Returns: {next_state, NextStateName, NextStateData} | +%% {next_state, NextStateName, NextStateData, Timeout} | +%% {reply, Reply, NextStateName, NextStateData} | +%% {reply, Reply, NextStateName, NextStateData, Timeout} | +%% {stop, Reason, NewStateData} | +%% {stop, Reason, Reply, NewStateData} +%%---------------------------------------------------------------------- +handle_sync_event(Event, From, StateName, StateData) -> + Reply = ok, + {reply, Reply, StateName, StateData}. + +code_change(OldVsn, StateName, StateData, Extra) -> + {ok, StateName, StateData}. + +%%---------------------------------------------------------------------- +%% Func: handle_info/3 +%% Returns: {next_state, NextStateName, NextStateData} | +%% {next_state, NextStateName, NextStateData, Timeout} | +%% {stop, Reason, NewStateData} +%%---------------------------------------------------------------------- +handle_info(_, StateName, StateData) -> + {next_state, StateName, StateData}. + +%%---------------------------------------------------------------------- +%% Func: terminate/3 +%% Purpose: Shutdown the fsm +%% Returns: any +%%---------------------------------------------------------------------- +terminate(Reason, StateName, StateData) -> + ok. + +%%%---------------------------------------------------------------------- +%%% Internal functions +%%%---------------------------------------------------------------------- + +receiver(Socket, C2SPid) -> + XMLStreamPid = xml_stream:start(C2SPid), + receiver(Socket, C2SPid, XMLStreamPid). + +receiver(Socket, C2SPid, XMLStreamPid) -> + case gen_tcp:recv(Socket, 0) of + {ok, Text} -> + xml_stream:send_text(XMLStreamPid, Text), + receiver(Socket, C2SPid, XMLStreamPid); + {error, Reason} -> + exit(XMLStreamPid, closed), + gen_fsm:send_event(C2SPid, closed), + ok + end. + diff --git a/src/mod_private.erl b/src/mod_private.erl index eb14f804c..d265088d0 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -58,7 +58,7 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> [{"code", "500"}], [{xmlcdata, "Internal Server Error"}]}]}; Res -> - {iq, ID, error, XMLNS, + {iq, ID, result, XMLNS, [{xmlelement, Name, Attrs, Res}]} end end; diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 22a1d1855..ca0801238 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -18,6 +18,7 @@ get_subscription_lists/1, in_subscription/3, out_subscription/3, + set_items/2, remove_user/1]). -include_lib("mnemosyne/include/mnemosyne.hrl"). @@ -470,3 +471,76 @@ remove_user(User) -> end, mnesia:transaction(F). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +set_items(User, SubEl) -> + {xmlelement, Name, Attrs, Els} = SubEl, + F = fun() -> + lists:foreach(fun(El) -> process_item_set_t(User, El) end, Els) + end, + mnesia:transaction(F). + +process_item_set_t(User, XItem) -> + {xmlelement, Name, Attrs, Els} = XItem, + JID = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)), + LUser = jlib:tolower(User), + case JID of + error -> + ok; + _ -> + LJID = jlib:jid_tolower(JID), + Res = mnesia:read({roster, {LUser, LJID}}), + Item = #roster{uj = {LUser, LJID}, + user = LUser, + jid = JID}, + Item1 = process_item_attrs_ws(Item, Attrs), + Item2 = process_item_els(Item1, Els), + case Item2#roster.subscription of + remove -> + mnesia:delete({roster, {LUser, LJID}}); + _ -> + mnesia:write(Item2) + end + end. + + +process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) -> + case Attr of + "jid" -> + case jlib:string_to_jid(Val) of + error -> + process_item_attrs_ws(Item, Attrs); + JID -> + process_item_attrs_ws(Item#roster{jid = JID}, Attrs) + end; + "name" -> + process_item_attrs_ws(Item#roster{name = Val}, Attrs); + "subscription" -> + case Val of + "remove" -> + process_item_attrs_ws(Item#roster{subscription = remove}, + Attrs); + "none" -> + process_item_attrs_ws(Item#roster{subscription = none}, + Attrs); + "both" -> + process_item_attrs_ws(Item#roster{subscription = both}, + Attrs); + "from" -> + process_item_attrs_ws(Item#roster{subscription = from}, + Attrs); + "to" -> + process_item_attrs_ws(Item#roster{subscription = to}, + Attrs); + _ -> + process_item_attrs_ws(Item, Attrs) + end; + "ask" -> + process_item_attrs_ws(Item, Attrs); + _ -> + XAttrs = Item#roster.xattrs, + process_item_attrs_ws(Item#roster{xattrs = [{Attr, Val} | XAttrs]}, + Attrs) + end; +process_item_attrs_ws(Item, []) -> + Item.