aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd.cfg.example3
-rw-r--r--src/web/ejabberd_http.erl34
-rw-r--r--src/web/ejabberd_web.erl10
-rw-r--r--src/web/ejabberd_web_admin.erl153
4 files changed, 174 insertions, 26 deletions
diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example
index cae56ec53..2285ef84a 100644
--- a/src/ejabberd.cfg.example
+++ b/src/ejabberd.cfg.example
@@ -91,8 +91,9 @@
[{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]},
{5223, ejabberd_c2s, [{access, c2s}, ssl, {certfile, "./ssl.pem"}]},
{5269, ejabberd_s2s_in, [{shaper, s2s_shaper}]},
+ {5280, ejabberd_http, [http_poll, web_admin]},
{8888, ejabberd_service, [{access, all},
- {hosts, ["conference.e.localhost", "muc.e.localhost"],
+ {hosts, ["icq.localhost", "sms.localhost"],
[{password, "secret"}]}]}
]}.
diff --git a/src/web/ejabberd_http.erl b/src/web/ejabberd_http.erl
index 6ef8a4032..0723fd572 100644
--- a/src/web/ejabberd_http.erl
+++ b/src/web/ejabberd_http.erl
@@ -25,7 +25,9 @@
request_path,
request_auth,
request_content_length,
- request_lang = "en"
+ request_lang = "en",
+ use_http_poll = false,
+ use_web_admin = false
}).
@@ -49,9 +51,15 @@ start_link({SockMod, Socket}, Opts) ->
ssl ->
ssl:setopts(Socket, [{packet, http}, {recbuf, 8192}])
end,
+ UseHTTPPoll = lists:member(http_poll, Opts),
+ UseWebAdmin = lists:member(web_admin, Opts),
+ io:format("S: ~p~n", [{UseHTTPPoll, UseWebAdmin}]),
{ok, proc_lib:spawn_link(ejabberd_http,
receive_headers,
- [#state{sockmod = SockMod, socket = Socket}])}.
+ [#state{sockmod = SockMod,
+ socket = Socket,
+ use_http_poll = UseHTTPPoll,
+ use_web_admin = UseWebAdmin}])}.
send_text(State, Text) ->
@@ -93,7 +101,10 @@ receive_headers(State) ->
ssl ->
ssl:setopts(Socket, [{packet, http}])
end,
- receive_headers(#state{sockmod = SockMod, socket = Socket});
+ receive_headers(#state{sockmod = SockMod,
+ socket = Socket,
+ use_http_poll = State#state.use_http_poll,
+ use_web_admin = State#state.use_web_admin});
{error, _Reason} ->
ok;
_ ->
@@ -105,7 +116,9 @@ receive_headers(State) ->
process_request(#state{request_method = 'GET',
request_path = {abs_path, Path},
request_auth = Auth,
- request_lang = Lang}) ->
+ request_lang = Lang,
+ use_http_poll = UseHTTPPoll,
+ use_web_admin = UseWebAdmin}) ->
User = case Auth of
{U, P} ->
case ejabberd_auth:check_password(U, P) of
@@ -136,7 +149,10 @@ process_request(#state{request_method = 'GET',
q = LQuery,
user = User,
lang = Lang},
- case ejabberd_web:process_get(Request) of
+ io:format("~p~n", [{{UseHTTPPoll, UseWebAdmin},
+ Request}]),
+ case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin},
+ Request) of
El when element(1, El) == xmlelement ->
make_xhtml_output(200, [], El);
{Status, Headers, El} when
@@ -157,7 +173,10 @@ process_request(#state{request_method = 'POST',
request_content_length = Len,
request_lang = Lang,
sockmod = SockMod,
- socket = Socket} = State) when is_integer(Len) ->
+ socket = Socket,
+ use_http_poll = UseHTTPPoll,
+ use_web_admin = UseWebAdmin} = State)
+ when is_integer(Len) ->
User = case Auth of
{U, P} ->
case ejabberd_auth:check_password(U, P) of
@@ -197,7 +216,8 @@ process_request(#state{request_method = 'POST',
user = User,
data = Data,
lang = Lang},
- case ejabberd_web:process_get(Request) of
+ case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin},
+ Request) of
El when element(1, El) == xmlelement ->
make_xhtml_output(200, [], El);
{Status, Headers, El} when
diff --git a/src/web/ejabberd_web.erl b/src/web/ejabberd_web.erl
index b59641c44..4ef511e52 100644
--- a/src/web/ejabberd_web.erl
+++ b/src/web/ejabberd_web.erl
@@ -12,7 +12,7 @@
%% External exports
-export([make_xhtml/1,
- process_get/1]).
+ process_get/2]).
-include("ejabberd.hrl").
-include("jlib.hrl").
@@ -49,7 +49,8 @@ make_xhtml(Els) ->
{"value", Value}])).
-process_get(#request{user = User,
+process_get({_, true},
+ #request{user = User,
path = ["admin" | RPath],
q = Query,
lang = Lang} = Request) ->
@@ -69,13 +70,14 @@ process_get(#request{user = User,
[{xmlcdata, "401 Unauthorized"}]}])}
end;
-process_get(#request{user = User,
+process_get({true, _},
+ #request{user = User,
path = ["http-poll" | RPath],
q = Query,
lang = Lang} = Request) ->
ejabberd_http_poll:process_request(Request#request{path = RPath});
-process_get(_Request) ->
+process_get(_, _Request) ->
{404, [], make_xhtml([?XC("h1", "Not found")])}.
diff --git a/src/web/ejabberd_web_admin.erl b/src/web/ejabberd_web_admin.erl
index 46801bc1f..c021fde2b 100644
--- a/src/web/ejabberd_web_admin.erl
+++ b/src/web/ejabberd_web_admin.erl
@@ -1,7 +1,7 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_web_admin.erl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
-%%% Purpose :
+%%% Purpose : Administration web interface
%%% Created : 9 Apr 2004 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
@@ -543,7 +543,7 @@ process_admin(#request{user = User,
ACLs = lists:flatten(io_lib:format("~p.", [ets:tab2list(acl)])),
make_xhtml([?XCT("h1", "ejabberd ACLs configuration")] ++
case Res of
- ok -> [?CT("submited"), ?P];
+ ok -> [?CT("submitted"), ?P];
error -> [?CT("bad format"), ?P];
nothing -> []
end ++
@@ -584,7 +584,7 @@ process_admin(#request{method = Method,
ACLs = lists:keysort(2, ets:tab2list(acl)),
make_xhtml([?XCT("h1", "ejabberd ACLs configuration")] ++
case Res of
- ok -> [?CT("submited"), ?P];
+ ok -> [?CT("submitted"), ?P];
error -> [?CT("bad format"), ?P];
nothing -> []
end ++
@@ -651,7 +651,7 @@ process_admin(#request{user = User,
[{{access, '$1', '$2'}}]}])])),
make_xhtml([?XC("h1", "ejabberd access rules configuration")] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -689,7 +689,7 @@ process_admin(#request{method = Method,
[{{access, '$1', '$2'}}]}]),
make_xhtml([?XC("h1", "ejabberd access rules configuration")] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -730,7 +730,7 @@ process_admin(#request{method = Method,
make_xhtml([?XC("h1",
"'" ++ SName ++ "' access rule configuration")] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -1103,7 +1103,7 @@ user_info(User, Query, Lang) ->
?INPUTT("submit", "chpassword", "Change Password")],
[?XC("h1", "User: " ++ User)] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -1174,12 +1174,23 @@ search_running_node(SNode, [Node | Nodes]) ->
end.
get_node(Node, [], Query, Lang) ->
- [?XC("h1", "Node: " ++ atom_to_list(Node)),
- ?XE("ul",
- [?LI([?ACT("db/", "DB Management")]),
- ?LI([?ACT("backup/", "Backup Management")]),
- ?LI([?ACT("statistics/", "Statistics")])
- ])];
+ Res = node_parse_query(Node, Query),
+ [?XC("h1", "Node: " ++ atom_to_list(Node))] ++
+ case Res of
+ ok -> [?C("submitted"), ?P];
+ error -> [?C("bad format"), ?P];
+ nothing -> []
+ end ++
+ [?XE("ul",
+ [?LI([?ACT("db/", "DB Management")]),
+ ?LI([?ACT("backup/", "Backup Management")]),
+ ?LI([?ACT("stats/", "Statistics")])
+ ]),
+ ?XAE("form", [{"method", "post"}],
+ [?INPUTT("submit", "restart", "Restart"),
+ ?C(" "),
+ ?INPUTT("submit", "stop", "Stop")])
+ ];
get_node(Node, ["db"], Query, Lang) ->
case rpc:call(Node, mnesia, system_info, [tables]) of
@@ -1224,7 +1235,7 @@ get_node(Node, ["db"], Query, Lang) ->
end, STables),
[?XC("h1", "DB Tables at " ++ atom_to_list(Node))] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -1249,6 +1260,7 @@ get_node(Node, ["db"], Query, Lang) ->
end;
get_node(Node, ["backup"], Query, Lang) ->
+ Res = node_backup_parse_query(Node, Query),
[?XC("h1", "Backup Management at " ++ atom_to_list(Node)),
?XAE("form", [{"method", "post"}],
[?XAE("table", [],
@@ -1292,10 +1304,77 @@ get_node(Node, ["backup"], Query, Lang) ->
])
])])];
+get_node(Node, ["stats"], Query, Lang) ->
+ UpTime = rpc:call(Node, erlang, statistics, [wall_clock]),
+ UpTimeS = io_lib:format("~.3f", [element(1, UpTime)/1000]),
+ CPUTime = rpc:call(Node, erlang, statistics, [runtime]),
+ CPUTimeS = io_lib:format("~.3f", [element(1, CPUTime)/1000]),
+ Users = length(
+ rpc:call(Node, ejabberd_sm, dirty_get_my_sessions_list, [])),
+ TransactionsCommited =
+ rpc:call(Node, mnesia, system_info, [transaction_commits]),
+ TransactionsAborted =
+ rpc:call(Node, mnesia, system_info, [transaction_failures]),
+ TransactionsRestarted =
+ rpc:call(Node, mnesia, system_info, [transaction_restarts]),
+ TransactionsLogged =
+ rpc:call(Node, mnesia, system_info, [transaction_log_writes]),
+
+ [?XC("h1", atom_to_list(Node) ++ " statistics"),
+ ?XAE("table", [],
+ [?XE("tbody",
+ [?XE("tr", [?XCT("td", "Uptime"),
+ ?XAC("td", [{"class", "alignright"}],
+ UpTimeS)]),
+ ?XE("tr", [?XCT("td", "CPU Time"),
+ ?XAC("td", [{"class", "alignright"}],
+ CPUTimeS)]),
+ ?XE("tr", [?XCT("td", "Authentificated users"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(Users))]),
+ ?XE("tr", [?XCT("td", "Transactions commited"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(TransactionsCommited))]),
+ ?XE("tr", [?XCT("td", "Transactions aborted"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(TransactionsAborted))]),
+ ?XE("tr", [?XCT("td", "Transactions restarted"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(TransactionsRestarted))]),
+ ?XE("tr", [?XCT("td", "Transactions logged"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(TransactionsLogged))])
+ ])
+ ])];
+
get_node(Node, NPath, Query, Lang) ->
[?XC("h1", "Not found")].
+node_parse_query(Node, Query) ->
+ case lists:keysearch("restart", 1, Query) of
+ {value, _} ->
+ case rpc:call(Node, init, restart, []) of
+ {badrpc, _Reason} ->
+ error;
+ _ ->
+ ok
+ end;
+ _ ->
+ case lists:keysearch("delete", 1, Query) of
+ {value, _} ->
+ case rpc:call(Node, init, restart, []) of
+ {badrpc, _Reason} ->
+ error;
+ _ ->
+ ok
+ end;
+ _ ->
+ nothing
+ end
+ end.
+
+
db_storage_select(ID, Opt, Lang) ->
?XAE("select", [{"name", "table" ++ ID}],
lists:map(
@@ -1345,3 +1424,49 @@ node_db_parse_query(Node, Tables, Query) ->
end, Tables),
ok.
+node_backup_parse_query(Node, Query) ->
+ lists:foldl(
+ fun(Action, nothing) ->
+ case lists:keysearch(Action, 1, Query) of
+ {value, _} ->
+ case lists:keysearch(Action ++ "path", 1, Query) of
+ {value, {_, Path}} ->
+ Res =
+ case Action of
+ "store" ->
+ rpc:call(Node, mnesia,
+ backup, [Path]);
+ "restore" ->
+ rpc:call(Node, mnesia,
+ restore,
+ [Path, [{default_op,
+ keep_tables}]]);
+ "fallback" ->
+ rpc:call(Node, mnesia,
+ install_fallback, [Path]);
+ "dump" ->
+ rpc:call(Node, mnesia,
+ dump_to_textfile, [Path]);
+ "load" ->
+ rpc:call(Node, mnesia,
+ load_textfile, [Path])
+ end,
+ case Res of
+ {error, _Reason} ->
+ error;
+ {badrpc, _Reason} ->
+ error;
+ _ ->
+ ok
+ end;
+ _ ->
+ error
+ end;
+ _ ->
+ nothing
+ end;
+ (_Action, Res) ->
+ Res
+ end, nothing, ["store", "restore", "fallback", "dump", "load"]).
+
+