1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
$NetBSD: patch-ai,v 1.1 2008/11/12 13:13:59 martti Exp $
Modified to use IPv6/v4 patch (https://support.process-one.net/browse/EJAB-389)
--- src/web/ejabberd_web_admin.erl.orig 2008-08-27 12:37:52.000000000 +0300
+++ src/web/ejabberd_web_admin.erl
@@ -1806,15 +1806,21 @@ get_node(global, Node, ["ports"], Query,
ok;
{'EXIT', _Reason} ->
error;
+ {is_added, ok} ->
+ ok;
+ {is_added, {error, Reason}} ->
+ {error, io_lib:format("~p", [Reason])};
_ ->
nothing
end,
+ %% TODO: This sorting does not work when [{{Port, IP}, Module, Opts}]
NewPorts = lists:sort(
rpc:call(Node, ejabberd_config, get_local_option, [listen])),
[?XC("h1", ?T("Listened Ports at ") ++ atom_to_list(Node))] ++
case Res of
ok -> [?CT("Submitted"), ?P];
error -> [?CT("Bad format"), ?P];
+ {error, ReasonT} -> [?CT("Problem: "), ?C(ReasonT), ?P];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -2052,58 +2058,76 @@ node_ports_to_xhtml(Ports, Lang) ->
[?XE("thead",
[?XE("tr",
[?XCT("td", "Port"),
+ ?XCT("td", "IP"),
?XCT("td", "Module"),
?XCT("td", "Options")
])]),
?XE("tbody",
lists:map(
- fun({Port, Module, Opts} = _E) ->
- SPort = integer_to_list(Port),
+ fun({PortIP, Module, Opts} = _E) ->
+ {_Port, SPort, _TIP, SIP, SSPort, OptsClean} =
+ get_port_data(PortIP, Opts),
SModule = atom_to_list(Module),
%%ID = term_to_id(E),
?XE("tr",
- [?XC("td", SPort),
- ?XE("td", [?INPUT("text", "module" ++ SPort,
- SModule)]),
- ?XE("td", [?INPUTS("text", "opts" ++ SPort,
- term_to_string(Opts), "40")]),
- ?XE("td", [?INPUTT("submit", "add" ++ SPort,
+ [?XAE("td", [{"size", "6"}], [?C(SPort)]),
+ ?XAE("td", [{"size", "15"}], [?C(SIP)]),
+ ?XE("td", [?INPUTS("text", "module" ++ SSPort,
+ SModule, "15")]),
+ ?XE("td", [?INPUTS("text", "opts" ++ SSPort,
+ term_to_string(OptsClean), "40")]),
+ ?XE("td", [?INPUTT("submit", "add" ++ SSPort,
"Update")]),
- ?XE("td", [?INPUTT("submit", "delete" ++ SPort,
+ ?XE("td", [?INPUTT("submit", "delete" ++ SSPort,
"Delete")])
]
)
end, Ports) ++
[?XE("tr",
[?XE("td", [?INPUTS("text", "portnew", "", "6")]),
- ?XE("td", [?INPUT("text", "modulenew", "")]),
- ?XE("td", [?INPUTS("text", "optsnew", "", "40")]),
+ ?XE("td", [?INPUTS("text", "ipnew", "0.0.0.0", "15")]),
+ ?XE("td", [?INPUTS("text", "modulenew", "", "17")]),
+ ?XE("td", [?INPUTS("text", "optsnew", "[]", "40")]),
?XAE("td", [{"colspan", "2"}],
[?INPUTT("submit", "addnew", "Add New")])
]
)]
)]).
+get_port_data(PortIP, Opts) ->
+ {Port, IPT, IPS, _IPV, OptsClean} = ejabberd_listener:parse_listener_portip(PortIP, Opts),
+ SPort = io_lib:format("~p", [Port]),
+
+ SSPort = lists:flatten(
+ lists:map(
+ fun(N) -> io_lib:format("~.16b", [N]) end,
+ binary_to_list(crypto:md5(SPort++IPS)))),
+ {Port, SPort, IPT, IPS, SSPort, OptsClean}.
node_ports_parse_query(Node, Ports, Query) ->
lists:foreach(
- fun({Port, _Module1, _Opts1}) ->
- SPort = integer_to_list(Port),
- case lists:keysearch("add" ++ SPort, 1, Query) of
+ fun({PortIP, _Module1, Opts1}) ->
+ {Port, _SPort, TIP, _SIP, SSPort, _OptsClean} =
+ get_port_data(PortIP, Opts1),
+ case lists:keysearch("add" ++ SSPort, 1, Query) of
{value, _} ->
+ PortIP2 = {Port, TIP},
{{value, {_, SModule}}, {value, {_, SOpts}}} =
- {lists:keysearch("module" ++ SPort, 1, Query),
- lists:keysearch("opts" ++ SPort, 1, Query)},
+ {lists:keysearch("module" ++ SSPort, 1, Query),
+ lists:keysearch("opts" ++ SSPort, 1, Query)},
Module = list_to_atom(SModule),
{ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
{ok, Opts} = erl_parse:parse_term(Tokens),
- rpc:call(Node, ejabberd_listener, delete_listener, [Port]),
- rpc:call(Node, ejabberd_listener, add_listener, [Port, Module, Opts]),
- throw(submitted);
+ rpc:call(Node, ejabberd_listener, delete_listener,
+ [PortIP2]),
+ R=rpc:call(Node, ejabberd_listener, add_listener,
+ [PortIP2, Module, Opts]),
+ throw({is_added, R});
_ ->
- case lists:keysearch("delete" ++ SPort, 1, Query) of
+ case lists:keysearch("delete" ++ SSPort, 1, Query) of
{value, _} ->
- rpc:call(Node, ejabberd_listener, delete_listener, [Port]),
+ rpc:call(Node, ejabberd_listener, delete_listener,
+ [PortIP]),
throw(submitted);
_ ->
ok
@@ -2113,17 +2137,28 @@ node_ports_parse_query(Node, Ports, Quer
case lists:keysearch("addnew", 1, Query) of
{value, _} ->
{{value, {_, SPort}},
+ {value, {_, STIP}}, %% It is a string that may represent a tuple
{value, {_, SModule}},
{value, {_, SOpts}}} =
{lists:keysearch("portnew", 1, Query),
+ lists:keysearch("ipnew", 1, Query),
lists:keysearch("modulenew", 1, Query),
lists:keysearch("optsnew", 1, Query)},
- Port = list_to_integer(SPort),
+ {ok, Toks, _} = erl_scan:string(SPort ++ "."),
+ {ok, Port2} = erl_parse:parse_term(Toks),
+ {ok, ToksIP, _} = erl_scan:string(STIP ++ "."),
+ STIP2 = case erl_parse:parse_term(ToksIP) of
+ {ok, IPTParsed} -> IPTParsed;
+ {error, _} -> STIP
+ end,
Module = list_to_atom(SModule),
{ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
{ok, Opts} = erl_parse:parse_term(Tokens),
- rpc:call(Node, ejabberd_listener, add_listener, [Port, Module, Opts]),
- throw(submitted);
+ {Port2, _SPort, IP2, _SIP, _SSPort, OptsClean} =
+ get_port_data({Port2, STIP2}, Opts),
+ R=rpc:call(Node, ejabberd_listener, add_listener,
+ [{Port2, IP2}, Module, OptsClean]),
+ throw({is_added, R});
_ ->
ok
end.
|