diff --git a/TODO b/TODO index 87f4691ea..30f722030 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,4 @@ +admin interface S2S timeouts iq:browse(?) SVR DNS records diff --git a/src/acl.erl b/src/acl.erl index 109d4edd6..b9c231475 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -22,8 +22,12 @@ add(ACLName, ACLData) -> ets:insert(acls, {ACLName, ACLData}). match_rule(Rule, JID) -> - ACLs = ejabberd_config:get_option(Rule), - match_acls(ACLs, JID). + case ejabberd_config:get_option(Rule) of + undefined -> + deny; + ACLs -> + match_acls(ACLs, JID) + end. match_acls([], _) -> deny; diff --git a/src/ejabberd.cfg b/src/ejabberd.cfg index 538c7918f..6d3d6521d 100644 --- a/src/ejabberd.cfg +++ b/src/ejabberd.cfg @@ -2,12 +2,18 @@ {acl, admin, {user, "aleksey"}}. {acl, admin, {user, "ermine"}}. +{acl, admin, {user, "test"}}. +{acl, admin, {user, "aleksey", "jabber.ru"}}. +{acl, admin, {user, "ermine", "jabber.ru"}}. + {acl, jabberorg, {server, "jabber.org"}}. {acl, aleksey, {user, "aleksey", "jabber.ru"}}. {disco_admin, [{allow, admin}, {deny, all}]}. +{configure, [{allow, admin}]}. + {host, "e.localhost"}. {listen, [{5522, ejabberd_c2s, start, []}, diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index f96aab3ee..ddae487be 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -22,6 +22,7 @@ start() -> register(ejabberd_local, spawn(ejabberd_local, init, [])), mod_register:start(), mod_roster:start(), + mod_configure:start(), mod_disco:start(), mod_stats:start(), mod_vcard:start(), diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index a597a6247..d834dea5c 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -86,24 +86,40 @@ clean_table_from_bad_node(Node) -> end, mnesia:transaction(F). +%have_connection(FromTo) -> +% F = fun() -> +% [E] = mnesia:read({s2s, FromTo}) +% end, +% case mnesia:transaction(F) of +% {atomic, _} -> +% true; +% _ -> +% false +% end. + have_connection(FromTo) -> - F = fun() -> - [E] = mnesia:read({s2s, FromTo}) - end, - case mnesia:transaction(F) of - {atomic, _} -> + case catch mnesia:dirty_read(s2s, FromTo) of + [_] -> true; _ -> false end. +%get_key(FromTo) -> +% F = fun() -> +% [E] = mnesia:read({s2s, FromTo}), +% E +% end, +% case mnesia:transaction(F) of +% {atomic, E} -> +% E#s2s.key; +% _ -> +% "" +% end. + get_key(FromTo) -> - F = fun() -> - [E] = mnesia:read({s2s, FromTo}), - E - end, - case mnesia:transaction(F) of - {atomic, E} -> + case catch mnesia:dirty_read(s2s, FromTo) of + [E] -> E#s2s.key; _ -> "" diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index a86dce479..cbb695bea 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -297,18 +297,16 @@ route_message(From, To, Packet) -> get_user_resources(User) -> LUser = jlib:tolower(User), - F = fun() -> - mnemosyne:eval(query [X.ur || X <- table(session), - X.user = LUser] - end) - end, - case mnesia:transaction(F) of - {atomic, Rs} -> - lists:map(fun(R) -> element(2, R) end, Rs); - {aborted, Reason} -> - [] + case catch mnesia:dirty_index_read(session, LUser, #session.user) of + {'EXIT', Reason} -> + []; + Rs -> + lists:map(fun(R) -> + element(2, R#session.ur) + end, Rs) end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_presence(User, Resource, Priority) -> @@ -330,16 +328,13 @@ unset_presence(User, Resource) -> get_user_present_resources(User) -> LUser = jlib:tolower(User), - F = fun() -> - mnesia:index_read(presence, LUser, #presence.user) - end, - case mnesia:transaction(F) of - {atomic, Rs} -> + case catch mnesia:dirty_index_read(presence, LUser, #presence.user) of + {'EXIT', Reason} -> + []; + Rs -> lists:map(fun(R) -> {R#presence.priority, element(2, R#presence.ur)} - end, Rs); - {aborted, Reason} -> - [] + end, Rs) end. dirty_get_sessions_list() -> diff --git a/src/mod_configure.erl b/src/mod_configure.erl new file mode 100644 index 000000000..b72f180b5 --- /dev/null +++ b/src/mod_configure.erl @@ -0,0 +1,207 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_configure.erl +%%% Author : Alexey Shchepin +%%% Purpose : +%%% Created : 19 Jan 2003 by Alexey Shchepin +%%% Id : $Id$ +%%%---------------------------------------------------------------------- + +-module(mod_configure). +-author('alexey@sevcom.net'). +-vsn('$Revision$ '). + +-export([start/0, + process_local_iq/3]). + +-include("ejabberd.hrl"). +-include("namespaces.hrl"). + + +start() -> + ejabberd_local:register_iq_handler(?NS_XDATA, + ?MODULE, process_local_iq). + + +process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> + case acl:match_rule(configure, From) of + deny -> + {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error", + [{"code", "405"}], + [{xmlcdata, "Not Allowed"}]}]}; + allow -> + Lang = xml:get_tag_attr_s("xml:lang", SubEl), + case Type of + set -> + case xml:get_tag_attr_s("type", SubEl) of + "cancel" -> + {iq, ID, result, XMLNS, + [{xmlelement, "query", [{"xmlns", XMLNS}], []}]}; + "submit" -> + XData = jlib:parse_xdata_submit(SubEl), + case XData of + invalid -> + {iq, ID, error, XMLNS, + [SubEl, {xmlelement, "error", + [{"code", "400"}], + [{xmlcdata, "Bad Request"}]}]}; + _ -> + Node = + string:tokens( + xml:get_tag_attr_s("node", SubEl), + "/"), + case set_form(Node, Lang, XData) of + {result, Res} -> + {iq, ID, result, XMLNS, + [{xmlelement, "query", + [{"xmlns", XMLNS}], + Res + }]}; + {error, Code, Desc} -> + {iq, ID, error, XMLNS, + [SubEl, {xmlelement, "error", + [{"code", Code}], + [{xmlcdata, Desc}]}]} + end + end; + _ -> + {iq, ID, error, XMLNS, + [SubEl, {xmlelement, "error", + [{"code", "405"}], + [{xmlcdata, "Not Allowed"}]}]} + end; + get -> + Node = + string:tokens(xml:get_tag_attr_s("node", SubEl), "/"), + case get_form(Node, Lang) of + {result, Res} -> + {iq, ID, result, XMLNS, + [{xmlelement, "query", [{"xmlns", XMLNS}], + Res + }]}; + {error, Code, Desc} -> + {iq, ID, error, XMLNS, + [SubEl, {xmlelement, "error", + [{"code", Code}], + [{xmlcdata, Desc}]}]} + end + end + end. + +-define(TLFIELD(Type, Label, Var), + {xmlelement, "field", [{"type", Type}, + {"label", translate:translate(Lang, Label)}, + {"var", Var}], []}). + +-define(TABLEFIELD(Table, Val), + {xmlelement, "field", [{"type", "list-single"}, + {"label", atom_to_list(Table)}, + {"var", atom_to_list(Table)}], + [{xmlelement, "value", [], [{xmlcdata, atom_to_list(Val)}]}, + {xmlelement, "option", [{"label", + translate:translate(Lang, "RAM copy")}], + [{xmlelement, "value", [], [{xmlcdata, "ram_copies"}]}]}, + {xmlelement, "option", [{"label", + translate:translate(Lang, + "RAM and disc copy")}], + [{xmlelement, "value", [], [{xmlcdata, "disc_copies"}]}]}, + {xmlelement, "option", [{"label", + translate:translate(Lang, "Disk copy")}], + [{xmlelement, "value", [], [{xmlcdata, "disc_only_copies"}]}]}, + {xmlelement, "option", [{"label", + translate:translate(Lang, "Remote copy")}], + [{xmlelement, "value", [], [{xmlcdata, "unknown"}]}]} + ]}). + + + +get_form(["running nodes", ENode, "DB"], Lang) -> + case search_running_node(ENode) of + false -> + {error, "404", "Not Found"}; + Node -> + case rpc:call(Node, mnesia, system_info, [tables]) of + {badrpc, Reason} -> + {error, "500", "Internal Server Error"}; + Tables -> + {result, [{xmlelement, "title", [], + [{xmlcdata, + translate:translate( + Lang, "DB Tables Configuration")}]}, + {xmlelement, "instructions", [], + [{xmlcdata, + translate:translate( + Lang, "Choose storage type of tables")}]} | + lists:map( + fun(Table) -> + case rpc:call(Node, + mnesia, + table_info, + [Table, storage_type]) of + {badrpc, _} -> + ?TABLEFIELD(Table, unknown); + Type -> + ?TABLEFIELD(Table, Type) + end + end, Tables) + ]} + end + end; + +get_form(_, Lang) -> + {error, "503", "Service Unavailable"}. + + + +set_form(["running nodes", ENode, "DB"], Lang, XData) -> + case search_running_node(ENode) of + false -> + {error, "404", "Not Found"}; + Node -> + lists:foreach( + fun({SVar, SVals}) -> + % We believe that this allowed only for good peoples + Table = list_to_atom(SVar), + Type = case SVals of + ["unknown"] -> unknown; + ["ram_copies"] -> ram_copies; + ["disc_copies"] -> disc_copies; + ["disc_only_copies"] -> disc_only_copies; + _ -> false + end, + if + Type == false -> + ok; + Type == unknown -> + mnesia:del_table_copy(Table, Node); + true -> + case mnesia:add_table_copy(Table, Node, Type) of + {aborted, _} -> + mnesia:change_table_copy_type( + Table, Node, Type); + _ -> + ok + end + end + end, XData), + {result, []} + end; + +set_form(_, Lang, XData) -> + {error, "503", "Service Unavailable"}. + + + +search_running_node(SNode) -> + search_running_node(SNode, mnesia:system_info(running_db_nodes)). + +search_running_node(_, []) -> + false; +search_running_node(SNode, [Node | Nodes]) -> + case atom_to_list(Node) of + SNode -> + Node; + _ -> + search_running_node(SNode, Nodes) + end. + + diff --git a/src/mod_disco.erl b/src/mod_disco.erl index aee3fc13c..9bf9c6dcf 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -106,6 +106,13 @@ process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) -> feature_to_xml({?NS_STATS}) ] }]}; + ["running nodes", ENode, "DB"] -> + {iq, ID, result, XMLNS, [{xmlelement, + "query", + [{"xmlns", ?NS_DISCO_INFO}], + [feature_to_xml({?NS_XDATA}) + ] + }]}; _ -> {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error", @@ -122,7 +129,7 @@ domain_to_xml(Domain) -> {xmlelement, "item", [{"jid", Domain}], []}. --define(TOP_NODE(Name, Node), +-define(NODE(Name, Node), {xmlelement, "item", [{"jid", Server}, {"name", translate:translate(Lang, Name)}, @@ -135,11 +142,11 @@ get_local_items([], Server, Lang) -> ejabberd_router:dirty_get_all_routes()), {result, Domains ++ - [?TOP_NODE("Online Users", "online users"), - ?TOP_NODE("All Users", "all users"), - ?TOP_NODE("Outgoing S2S connections", "outgoing s2s"), - ?TOP_NODE("Running Nodes", "running nodes"), - ?TOP_NODE("Stopped Nodes", "stopped nodes") + [?NODE("Online Users", "online users"), + ?NODE("All Users", "all users"), + ?NODE("Outgoing S2S connections", "outgoing s2s"), + ?NODE("Running Nodes", "running nodes"), + ?NODE("Stopped Nodes", "stopped nodes") ]}; get_local_items(["online users"], Server, Lang) -> @@ -157,7 +164,11 @@ get_local_items(["running nodes"], Server, Lang) -> get_local_items(["stopped nodes"], Server, Lang) -> {result, get_stopped_nodes(Lang)}; -get_local_items(["running nodes", _], Server, Lang) -> +get_local_items(["running nodes", ENode], Server, Lang) -> + {result, + [?NODE("DB", "running nodes/" ++ ENode ++ "/DB")]}; + +get_local_items(["running nodes", ENode, "DB"], Server, Lang) -> {result, []}; get_local_items(_, _, _) ->