unauthorized
end.
-make_xhtml(Els, global, Lang) ->
- MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_main, [], [Lang]),
- MenuItems2 = [?LI([?AC("/admin/"++MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
- {200, [html],
- {xmlelement, "html", [{"xmlns", "http://www.w3.org/1999/xhtml"},
- {"xml:lang", Lang},
- {"lang", Lang}],
- [{xmlelement, "head", [],
- [?XCT("title", "ejabberd Web Admin"),
- {xmlelement, "meta", [{"http-equiv", "Content-Type"},
- {"content", "text/html; charset=utf-8"}], []},
- {xmlelement, "link", [{"href", "/admin/favicon.ico"},
- {"type", "image/x-icon"},
- {"rel", "shortcut icon"}], []},
- {xmlelement, "link", [{"href", "/admin/style.css"},
- {"type", "text/css"},
- {"rel", "stylesheet"}], []}]},
- ?XE("body",
- [?XAE("div",
- [{"id", "container"}],
- [?XAE("div",
- [{"id", "header"}],
- [?XE("h1",
- [?ACT("/admin/", "Administration")]
- )]),
- ?XAE("div",
- [{"id", "navigation"}],
- [?XE("ul",
- [?LI([?ACT("/admin/acls/", "Access Control Lists")]),
- ?LI([?ACT("/admin/access/", "Access Rules")]),
- ?LI([?ACT("/admin/vhosts/", "Virtual Hosts")]),
- ?LI([?ACT("/admin/nodes/", "Nodes")]),
- ?LI([?ACT("/admin/stats/", "Statistics")])
- ] ++ MenuItems2
- )]),
- ?XAE("div",
- [{"id", "content"}],
- Els),
- ?XAE("div",
- [{"id", "clearcopyright"}],
- [{xmlcdata, ""}])]),
- ?XAE("div",
- [{"id", "copyrightouter"}],
- [?XAE("div",
- [{"id", "copyright"}],
- [?XC("p",
- "ejabberd (c) 2002-2008 ProcessOne")
- ])])])
- ]}};
-
make_xhtml(Els, Host, Lang) ->
- Base = "/admin/server/" ++ Host ++ "/",
- MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host, Lang]),
- MenuItems2 = [?LI([?AC(Base ++ MI_uri ++ "/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
+ make_xhtml(Els, Host, cluster, Lang).
+
+%% @spec (Els, Host, Node, Lang)
+%% where Host = global | string()
+%% Node = cluster | atom()
+make_xhtml(Els, Host, Node, Lang) ->
+ Base = get_base_path(Host, cluster), %% Enforcing 'cluster' on purpose here
+ MenuItems = make_navigation(Host, Node, Lang),
{200, [html],
{xmlelement, "html", [{"xmlns", "http://www.w3.org/1999/xhtml"},
{"xml:lang", Lang},
[?XCT("title", "ejabberd Web Admin"),
{xmlelement, "meta", [{"http-equiv", "Content-Type"},
{"content", "text/html; charset=utf-8"}], []},
- {xmlelement, "link", [{"href", "/admin/favicon.ico"},
+ {xmlelement, "link", [{"href", Base ++ "favicon.ico"},
{"type", "image/x-icon"},
{"rel", "shortcut icon"}], []},
{xmlelement, "link", [{"href", Base ++ "style.css"},
?XAE("div",
[{"id", "navigation"}],
[?XE("ul",
- [?LI([?XAE("div",
- [{"id", "navheadhost"}],
- [?AC(Base, Host)]
- )]),
- ?LI([?ACT(Base ++ "acls/", "Access Control Lists")]),
- ?LI([?ACT(Base ++ "access/", "Access Rules")]),
- ?LI([?ACT(Base ++ "users/", "Users")]),
- ?LI([?ACT(Base ++ "online-users/", "Online Users")]),
- ?LI([?ACT(Base ++ "last-activity/", "Last Activity")]),
- ?LI([?ACT(Base ++ "nodes/", "Nodes")]),
- ?LI([?ACT(Base ++ "stats/", "Statistics")])
- ] ++ MenuItems2
+ MenuItems
)]),
?XAE("div",
[{"id", "content"}],
])])])
]}}.
+get_base_path(global, cluster) -> "/admin/";
+get_base_path(Host, cluster) -> "/admin/server/" ++ Host ++ "/";
+get_base_path(global, Node) -> "/admin/node/" ++ atom_to_list(Node) ++ "/";
+get_base_path(Host, Node) -> "/admin/server/" ++ Host ++ "/node/" ++ atom_to_list(Node) ++ "/".
+
css(Host) ->
- Base = case Host of
- global ->
- "/admin/";
- _ ->
- "/admin/server/" ++ Host ++ "/"
- end,
+ Base = get_base_path(Host, cluster),
"
html,body {
background: white;
#navigation ul {
position: absolute;
- top: 54px;
+ top: 65px;
left: 0;
padding: 0 1px 1px 1px;
margin: 0;
font-size: 8pt;
font-weight: bold;
background: #d47911;
- width: 13em;
+ width: 17em;
}
#navigation ul li {
background: #332;
}
-#navheadhost {
- text-align: left;
- border-bottom: 2px solid #d47911;
+ul li #navhead a, ul li #navheadsub a, ul li #navheadsubsub a {
+ text-align: center;
+ border-top: 2px solid #d47911;
+ border-bottom: 1px solid #d47911;
+}
+
+#navheadsub, #navitemsub {
+ border-left: 7px solid white;
+ margin-left: 2px solid #d47911;
+}
+
+#navheadsubsub, #navitemsubsub {
+ border-left: 14px solid white;
+ margin-left: 4px solid #d47911;
}
#lastactivity li {
#content {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
- padding-left: 13em;
+ padding-left: 17em;
padding-top: 5px;
}
"1c5dvhSU2BpKqBXl6R0ljYGS50R5zVC+tVD+vfE6YyUexE9x7g4AAAAASUVO"
"RK5CYII=").
+
process_admin(global,
#request{path = [],
lang = Lang}) ->
- MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_main, [], [Lang]),
- MenuItems2 = [?LI([?AC("/admin/"++MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
+ Base = get_base_path(global, cluster),
+ MenuItems2 = make_menu_items(global, cluster, Base, Lang),
make_xhtml([?XCT("h1", "Administration"),
?XE("ul",
[?LI([?ACT("/admin/acls/", "Access Control Lists"), ?C(" "),
process_admin(Host,
#request{path = [],
lang = Lang}) ->
- Base = "/admin/server/" ++ Host ++ "/",
- MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host, Lang]),
- MenuItems2 = [?LI([?AC(Base ++ MI_uri ++ "/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
+ Base = get_base_path(Host, cluster),
+ MenuItems2 = make_menu_items(Host, cluster, Base, Lang),
make_xhtml([?XCT("h1", "Administration"),
?XE("ul",
[?LI([?ACT(Base ++ "acls/", "Access Control Lists"), ?C(" "),
make_xhtml([?XCT("h1", "Node not found")], Host, Lang);
Node ->
Res = get_node(Host, Node, NPath, Query, Lang),
- make_xhtml(Res, Host, Lang)
+ make_xhtml(Res, Host, Node, Lang)
end;
process_admin(Host, #request{lang = Lang} = Request) ->
get_node(global, Node, [], Query, Lang) ->
Res = node_parse_query(Node, Query),
- MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_node, [], [Node, Lang]),
- MenuItems2 = [?LI([?AC(MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
+ Base = get_base_path(global, Node),
+ MenuItems2 = make_menu_items(global, Node, Base, Lang),
[?XC("h1", ?T("Node ") ++ atom_to_list(Node))] ++
case Res of
ok -> [?CT("Submitted"), ?P];
nothing -> []
end ++
[?XE("ul",
- [?LI([?ACT("db/", "Database")]),
- ?LI([?ACT("backup/", "Backup")]),
- ?LI([?ACT("ports/", "Listened Ports")]),
- ?LI([?ACT("stats/", "Statistics")]),
- ?LI([?ACT("update/", "Update")])
+ [?LI([?ACT(Base ++ "db/", "Database")]),
+ ?LI([?ACT(Base ++ "backup/", "Backup")]),
+ ?LI([?ACT(Base ++ "ports/", "Listened Ports")]),
+ ?LI([?ACT(Base ++ "stats/", "Statistics")]),
+ ?LI([?ACT(Base ++ "update/", "Update")])
] ++ MenuItems2),
?XAE("form", [{"action", ""}, {"method", "post"}],
[?INPUTT("submit", "restart", "Restart"),
];
get_node(Host, Node, [], _Query, Lang) ->
- MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host, [], [Host, Node, Lang]),
- MenuItems2 = [?LI([?AC(MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
+ Base = get_base_path(Host, Node),
+ MenuItems2 = make_menu_items(global, Node, Base, Lang),
[?XC("h1", ?T("Node ") ++ atom_to_list(Node)),
?XE("ul",
- [?LI([?ACT("modules/", "Modules")])] ++ MenuItems2)
+ [?LI([?ACT(Base ++ "modules/", "Modules")])] ++ MenuItems2)
];
get_node(global, Node, ["db"], Query, Lang) ->
{"Last-Modified", "Mon, 25 Feb 2008 13:23:30 GMT"}.
cache_control_public() ->
{"Cache-Control", "public"}.
+
+
+%%%
+%%% Navigation Menu
+%%%
+
+%% @spec (Host, Node, Lang) -> [LI]
+make_navigation(Host, Node, Lang) ->
+ HostNodeMenu = make_host_node_menu(Host, Node, Lang),
+ HostMenu = make_host_menu(Host, HostNodeMenu, Lang),
+ NodeMenu = make_node_menu(Host, Node, Lang),
+ Menu = make_server_menu(HostMenu, NodeMenu, Lang),
+ make_menu_items(Lang, Menu).
+
+%% @spec (Host, Node, Base, Lang) -> [LI]
+make_menu_items(global, cluster, Base, Lang) ->
+ HookItems = get_menu_items_hook(server, Lang),
+ make_menu_items(Lang, {Base, "", HookItems});
+
+make_menu_items(global, _Node, Base, Lang) ->
+ HookItems = get_menu_items_hook(node, Lang),
+ make_menu_items(Lang, {Base, "", HookItems});
+
+make_menu_items(Host, cluster, Base, Lang) ->
+ HookItems = get_menu_items_hook({host, Host}, Lang),
+ make_menu_items(Lang, {Base, "", HookItems});
+
+make_menu_items(Host, _Node, Base, Lang) ->
+ HookItems = get_menu_items_hook({hostnode, Host}, Lang),
+ make_menu_items(Lang, {Base, "", HookItems}).
+
+
+make_host_node_menu(global, _, _Lang) ->
+ {"", "", []};
+make_host_node_menu(_, cluster, _Lang) ->
+ {"", "", []};
+make_host_node_menu(Host, Node, Lang) ->
+ HostNodeBase = get_base_path(Host, Node),
+ HostNodeFixed = [{"modules/", "Modules"}],
+ HostNodeHook = get_menu_items_hook({hostnode, Host}, Lang),
+ {HostNodeBase, atom_to_list(Node), HostNodeFixed ++ HostNodeHook}.
+
+make_host_menu(global, _HostNodeMenu, _Lang) ->
+ {"", "", []};
+make_host_menu(Host, HostNodeMenu, Lang) ->
+ HostBase = get_base_path(Host, cluster),
+ HostFixed = [{"acls", "Access Control Lists"},
+ {"access", "Access Rules"},
+ {"users", "Users"},
+ {"online-users", "Online Users"},
+ {"last-activity", "Last Activity"},
+ {"nodes", "Nodes", HostNodeMenu},
+ {"stats", "Statistics"}],
+ HostHook = get_menu_items_hook({host, Host}, Lang),
+ {HostBase, Host, HostFixed ++ HostHook}.
+
+make_node_menu(_Host, cluster, _Lang) ->
+ {"", "", []};
+make_node_menu(global, Node, Lang) ->
+ NodeBase = get_base_path(global, Node),
+ NodeFixed = [{"db/", "Database"},
+ {"backup/", "Backup"},
+ {"ports/", "Listened Ports"},
+ {"stats/", "Statistics"},
+ {"update/", "Update"}],
+ NodeHook = get_menu_items_hook(node, Lang),
+ {NodeBase, atom_to_list(Node), NodeFixed ++ NodeHook};
+make_node_menu(_Host, _Node, _Lang) ->
+ {"", "", []}.
+
+make_server_menu(HostMenu, NodeMenu, Lang) ->
+ Base = get_base_path(global, cluster),
+ Fixed = [{"acls", "Access Control Lists"},
+ {"access", "Access Rules"},
+ {"vhosts", "Virtual Hosts", HostMenu},
+ {"nodes", "Nodes", NodeMenu},
+ {"stats", "Statistics"}],
+ Hook = get_menu_items_hook(server, Lang),
+ {Base, "ejabberd", Fixed ++ Hook}.
+
+
+get_menu_items_hook({hostnode, Host}, Lang) ->
+ ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host, [], [Host, Lang]);
+get_menu_items_hook({host, Host}, Lang) ->
+ ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host, Lang]);
+get_menu_items_hook(node, Lang) ->
+ ejabberd_hooks:run_fold(webadmin_menu_node, [], [Lang]);
+get_menu_items_hook(server, Lang) ->
+ ejabberd_hooks:run_fold(webadmin_menu_main, [], [Lang]).
+
+
+%% @spec (Lang::string(), Menu) -> [LI]
+%% where Menu = {MURI::string(), MName::string(), Items::[Item]}
+%% Item = {IURI::string(), IName::string()} | {IURI::string(), IName::string(), Menu}
+make_menu_items(Lang, Menu) ->
+ lists:reverse(make_menu_items2(Lang, 1, Menu)).
+
+make_menu_items2(Lang, Deep, {MURI, MName, _} = Menu) ->
+ Res = case MName of
+ "" -> [];
+ _ -> [make_menu_item(header, Deep, MURI, MName, Lang) ]
+ end,
+ make_menu_items2(Lang, Deep, Menu, Res).
+
+make_menu_items2(_, _Deep, {_, _, []}, Res) ->
+ Res;
+
+make_menu_items2(Lang, Deep, {MURI, MName, [Item | Items]}, Res) ->
+ Res2 = case Item of
+ {IURI, IName} ->
+ [make_menu_item(item, Deep, MURI++IURI++"/", IName, Lang) | Res];
+ {IURI, IName, SubMenu} ->
+ %%ResTemp = [?LI([?ACT(MURI ++ IURI ++ "/", IName)]) | Res],
+ ResTemp = [make_menu_item(item, Deep, MURI++IURI++"/", IName, Lang) | Res],
+ ResSubMenu = make_menu_items2(Lang, Deep+1, SubMenu),
+ ResSubMenu ++ ResTemp
+ end,
+ make_menu_items2(Lang, Deep, {MURI, MName, Items}, Res2).
+
+make_menu_item(header, 1, URI, Name, _Lang) ->
+ ?LI([?XAE("div", [{"id", "navhead"}], [?AC(URI, "~ "++Name++" ~")] )]);
+make_menu_item(header, 2, URI, Name, _Lang) ->
+ ?LI([?XAE("div", [{"id", "navheadsub"}], [?AC(URI, "~ "++Name++" ~")] )]);
+make_menu_item(header, 3, URI, Name, _Lang) ->
+ ?LI([?XAE("div", [{"id", "navheadsubsub"}], [?AC(URI, "~ "++Name++" ~")] )]);
+make_menu_item(item, 1, URI, Name, Lang) ->
+ ?LI([?XAE("div", [{"id", "navitem"}], [?ACT(URI, Name)] )]);
+make_menu_item(item, 2, URI, Name, Lang) ->
+ ?LI([?XAE("div", [{"id", "navitemsub"}], [?ACT(URI, Name)] )]);
+make_menu_item(item, 3, URI, Name, Lang) ->
+ ?LI([?XAE("div", [{"id", "navitemsubsub"}], [?ACT(URI, Name)] )]).