mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
* src/mod_muc/mod_muc_room.erl: Support for history management
(thanks to Sergei Golovan) * src/mod_stats.erl: Updated error codes (thanks to Sergei Golovan) * src/mod_irc/mod_irc.erl: Likewise * src/mod_configure.erl: "jabber:iq:data" replaced with "ejabber:config" namespace (thanks to Sergei Golovan) * src/mod_disco.erl: Likewise SVN Revision: 204
This commit is contained in:
parent
35bfd03669
commit
fdf25720e0
13
ChangeLog
13
ChangeLog
@ -1,3 +1,16 @@
|
|||||||
|
2004-02-15 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
|
* src/mod_muc/mod_muc_room.erl: Support for history management
|
||||||
|
(thanks to Sergei Golovan)
|
||||||
|
|
||||||
|
* src/mod_stats.erl: Updated error codes (thanks to Sergei
|
||||||
|
Golovan)
|
||||||
|
* src/mod_irc/mod_irc.erl: Likewise
|
||||||
|
|
||||||
|
* src/mod_configure.erl: "jabber:iq:data" replaced with
|
||||||
|
"ejabber:config" namespace (thanks to Sergei Golovan)
|
||||||
|
* src/mod_disco.erl: Likewise
|
||||||
|
|
||||||
2004-02-12 Alexey Shchepin <alexey@sevcom.net>
|
2004-02-12 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
* src/ejabberd_c2s.erl: Added <session/> to stream features
|
* src/ejabberd_c2s.erl: Added <session/> to stream features
|
||||||
|
@ -23,15 +23,15 @@
|
|||||||
|
|
||||||
start(Opts) ->
|
start(Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_IQDATA,
|
gen_iq_handler:add_iq_handler(ejabberd_local, ?NS_EJABBERD_CONFIG,
|
||||||
?MODULE, process_local_iq, IQDisc),
|
?MODULE, process_local_iq, IQDisc),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, ?NS_IQDATA,
|
gen_iq_handler:add_iq_handler(ejabberd_sm, ?NS_EJABBERD_CONFIG,
|
||||||
?MODULE, process_sm_iq, IQDisc),
|
?MODULE, process_sm_iq, IQDisc),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
stop() ->
|
stop() ->
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_IQDATA),
|
gen_iq_handler:remove_iq_handler(ejabberd_local, ?NS_EJABBERD_CONFIG),
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_IQDATA).
|
gen_iq_handler:remove_iq_handler(ejabberd_sm, ?NS_EJABBERD_CONFIG).
|
||||||
|
|
||||||
|
|
||||||
process_local_iq(From, _To, #iq{id = ID, type = Type,
|
process_local_iq(From, _To, #iq{id = ID, type = Type,
|
||||||
@ -43,38 +43,44 @@ process_local_iq(From, _To, #iq{id = ID, type = Type,
|
|||||||
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
|
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
|
||||||
case Type of
|
case Type of
|
||||||
set ->
|
set ->
|
||||||
case xml:get_tag_attr_s("type", SubEl) of
|
XDataEl = find_xdata_el(SubEl),
|
||||||
"cancel" ->
|
case XDataEl of
|
||||||
IQ#iq{type = result,
|
false ->
|
||||||
sub_el = [{xmlelement, "query",
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ACCEPTABLE]};
|
||||||
[{"xmlns", XMLNS}], []}]};
|
{xmlelement, _Name, Attrs, SubEls} ->
|
||||||
"submit" ->
|
case xml:get_attr_s("type", Attrs) of
|
||||||
XData = jlib:parse_xdata_submit(SubEl),
|
"cancel" ->
|
||||||
case XData of
|
IQ#iq{type = result,
|
||||||
invalid ->
|
sub_el = [{xmlelement, "query",
|
||||||
IQ#iq{type = error,
|
[{"xmlns", XMLNS}], []}]};
|
||||||
sub_el = [SubEl, ?ERR_BAD_REQUEST]};
|
"submit" ->
|
||||||
_ ->
|
XData = jlib:parse_xdata_submit(XDataEl),
|
||||||
Node =
|
case XData of
|
||||||
string:tokens(
|
invalid ->
|
||||||
xml:get_tag_attr_s("node", SubEl),
|
|
||||||
"/"),
|
|
||||||
case set_form(Node, Lang, XData) of
|
|
||||||
{result, Res} ->
|
|
||||||
IQ#iq{type = result,
|
|
||||||
sub_el =
|
|
||||||
[{xmlelement, "query",
|
|
||||||
[{"xmlns", XMLNS}],
|
|
||||||
Res
|
|
||||||
}]};
|
|
||||||
{error, Error} ->
|
|
||||||
IQ#iq{type = error,
|
IQ#iq{type = error,
|
||||||
sub_el = [SubEl, Error]}
|
sub_el = [SubEl, ?ERR_BAD_REQUEST]};
|
||||||
end
|
_ ->
|
||||||
end;
|
Node =
|
||||||
_ ->
|
string:tokens(
|
||||||
IQ#iq{type = error,
|
xml:get_tag_attr_s("node", SubEl),
|
||||||
sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
"/"),
|
||||||
|
case set_form(Node, Lang, XData) of
|
||||||
|
{result, Res} ->
|
||||||
|
IQ#iq{type = result,
|
||||||
|
sub_el =
|
||||||
|
[{xmlelement, "query",
|
||||||
|
[{"xmlns", XMLNS}],
|
||||||
|
Res
|
||||||
|
}]};
|
||||||
|
{error, Error} ->
|
||||||
|
IQ#iq{type = error,
|
||||||
|
sub_el = [SubEl, Error]}
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
IQ#iq{type = error,
|
||||||
|
sub_el = [SubEl, ?ERR_BAD_REQUEST]}
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
get ->
|
get ->
|
||||||
Node =
|
Node =
|
||||||
@ -137,27 +143,28 @@ get_form(["running nodes", ENode, "DB"], Lang) ->
|
|||||||
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
Tables ->
|
Tables ->
|
||||||
STables = lists:sort(Tables),
|
STables = lists:sort(Tables),
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "DB Tables Configuration")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "DB Tables Configuration")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Choose storage type of tables")}]} |
|
translate:translate(
|
||||||
lists:map(
|
Lang, "Choose storage type of tables")}]} |
|
||||||
fun(Table) ->
|
lists:map(
|
||||||
case rpc:call(Node,
|
fun(Table) ->
|
||||||
mnesia,
|
case rpc:call(Node,
|
||||||
table_info,
|
mnesia,
|
||||||
[Table, storage_type]) of
|
table_info,
|
||||||
{badrpc, _} ->
|
[Table, storage_type]) of
|
||||||
?TABLEFIELD(Table, unknown);
|
{badrpc, _} ->
|
||||||
Type ->
|
?TABLEFIELD(Table, unknown);
|
||||||
?TABLEFIELD(Table, Type)
|
Type ->
|
||||||
end
|
?TABLEFIELD(Table, Type)
|
||||||
end, STables)
|
end
|
||||||
]}
|
end, STables)
|
||||||
|
]}]}
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -171,217 +178,228 @@ get_form(["running nodes", ENode, "modules", "stop"], Lang) ->
|
|||||||
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
Modules ->
|
Modules ->
|
||||||
SModules = lists:sort(Modules),
|
SModules = lists:sort(Modules),
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Stop Modules")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Stop Modules")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Choose modules to stop")}]} |
|
translate:translate(
|
||||||
lists:map(fun(M) ->
|
Lang, "Choose modules to stop")}]} |
|
||||||
S = atom_to_list(M),
|
lists:map(fun(M) ->
|
||||||
?XFIELD("boolean", S, S, "0")
|
S = atom_to_list(M),
|
||||||
end, SModules)
|
?XFIELD("boolean", S, S, "0")
|
||||||
]}
|
end, SModules)
|
||||||
|
]}]}
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
get_form(["running nodes", ENode, "modules", "start"], Lang) ->
|
get_form(["running nodes", ENode, "modules", "start"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Start Modules")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Start Modules")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Enter list of {Module, [Options]}")}]},
|
translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-multi"},
|
Lang, "Enter list of {Module, [Options]}")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-multi"},
|
||||||
translate:translate(
|
{"label",
|
||||||
Lang, "List of modules to start")},
|
translate:translate(
|
||||||
{"var", "modules"}],
|
Lang, "List of modules to start")},
|
||||||
[{xmlelement, "value", [], [{xmlcdata, "[]."}]}]
|
{"var", "modules"}],
|
||||||
}
|
[{xmlelement, "value", [], [{xmlcdata, "[]."}]}]
|
||||||
]};
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["running nodes", ENode, "backup", "backup"], Lang) ->
|
get_form(["running nodes", ENode, "backup", "backup"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Backup to File")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Backup to File")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Enter path to backup file")}]},
|
translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-single"},
|
Lang, "Enter path to backup file")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-single"},
|
||||||
translate:translate(
|
{"label",
|
||||||
Lang, "Path to File")},
|
translate:translate(
|
||||||
{"var", "path"}],
|
Lang, "Path to File")},
|
||||||
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
{"var", "path"}],
|
||||||
}
|
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
||||||
]};
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["running nodes", ENode, "backup", "restore"], Lang) ->
|
get_form(["running nodes", ENode, "backup", "restore"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Restore Backup from File")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Restore Backup from File")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Enter path to backup file")}]},
|
translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-single"},
|
Lang, "Enter path to backup file")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-single"},
|
||||||
translate:translate(
|
{"label",
|
||||||
Lang, "Path to File")},
|
translate:translate(
|
||||||
{"var", "path"}],
|
Lang, "Path to File")},
|
||||||
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
{"var", "path"}],
|
||||||
}
|
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
||||||
]};
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["running nodes", ENode, "backup", "textfile"], Lang) ->
|
get_form(["running nodes", ENode, "backup", "textfile"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Dump Backup to Text File")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Dump Backup to Text File")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Enter path to text file")}]},
|
translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-single"},
|
Lang, "Enter path to text file")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-single"},
|
||||||
translate:translate(
|
{"label",
|
||||||
Lang, "Path to File")},
|
translate:translate(
|
||||||
{"var", "path"}],
|
Lang, "Path to File")},
|
||||||
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
{"var", "path"}],
|
||||||
}
|
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
||||||
]};
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["running nodes", ENode, "import", "file"], Lang) ->
|
get_form(["running nodes", ENode, "import", "file"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Import User from File")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Import User from File")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Enter path to jabberd1.4 spool file")}]},
|
translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-single"},
|
Lang, "Enter path to jabberd1.4 spool file")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-single"},
|
||||||
translate:translate(
|
{"label",
|
||||||
Lang, "Path to File")},
|
translate:translate(
|
||||||
{"var", "path"}],
|
Lang, "Path to File")},
|
||||||
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
{"var", "path"}],
|
||||||
}
|
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
||||||
]};
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["running nodes", ENode, "import", "dir"], Lang) ->
|
get_form(["running nodes", ENode, "import", "dir"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Import User from Dir")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Import User from Dir")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Enter path to jabberd1.4 spool dir")}]},
|
translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-single"},
|
Lang, "Enter path to jabberd1.4 spool dir")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-single"},
|
||||||
translate:translate(
|
{"label",
|
||||||
Lang, "Path to Dir")},
|
translate:translate(
|
||||||
{"var", "path"}],
|
Lang, "Path to Dir")},
|
||||||
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
{"var", "path"}],
|
||||||
}
|
[{xmlelement, "value", [], [{xmlcdata, ""}]}]
|
||||||
]};
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["config", "hostname"], Lang) ->
|
get_form(["config", "hostname"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Hostname Configuration")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Hostname Configuration")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Choose host name")}]},
|
translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-single"},
|
Lang, "Choose host name")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-single"},
|
||||||
translate:translate(Lang, "Host name")},
|
{"label",
|
||||||
{"var", "hostname"}],
|
translate:translate(Lang, "Host name")},
|
||||||
[{xmlelement, "value", [], [{xmlcdata, ?MYNAME}]}]}
|
{"var", "hostname"}],
|
||||||
]};
|
[{xmlelement, "value", [], [{xmlcdata, ?MYNAME}]}]}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["config", "acls"], Lang) ->
|
get_form(["config", "acls"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "ACLs Configuration")}]},
|
translate:translate(
|
||||||
%{xmlelement, "instructions", [],
|
Lang, "ACLs Configuration")}]},
|
||||||
% [{xmlcdata,
|
%{xmlelement, "instructions", [],
|
||||||
% translate:translate(
|
% [{xmlcdata,
|
||||||
% Lang, "")}]},
|
% translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-multi"},
|
% Lang, "")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-multi"},
|
||||||
translate:translate(Lang, "ACLs")},
|
{"label",
|
||||||
{"var", "acls"}],
|
translate:translate(Lang, "ACLs")},
|
||||||
lists:map(fun(S) ->
|
{"var", "acls"}],
|
||||||
{xmlelement, "value", [], [{xmlcdata, S}]}
|
lists:map(fun(S) ->
|
||||||
end,
|
{xmlelement, "value", [], [{xmlcdata, S}]}
|
||||||
string:tokens(
|
end,
|
||||||
lists:flatten(io_lib:format("~p.",
|
string:tokens(
|
||||||
[ets:tab2list(acl)])),
|
lists:flatten(io_lib:format("~p.",
|
||||||
"\n"))
|
[ets:tab2list(acl)])),
|
||||||
}
|
"\n"))
|
||||||
]};
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["config", "access"], Lang) ->
|
get_form(["config", "access"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Access Configuration")}]},
|
translate:translate(
|
||||||
%{xmlelement, "instructions", [],
|
Lang, "Access Configuration")}]},
|
||||||
% [{xmlcdata,
|
%{xmlelement, "instructions", [],
|
||||||
% translate:translate(
|
% [{xmlcdata,
|
||||||
% Lang, "")}]},
|
% translate:translate(
|
||||||
{xmlelement, "field", [{"type", "text-multi"},
|
% Lang, "")}]},
|
||||||
{"label",
|
{xmlelement, "field", [{"type", "text-multi"},
|
||||||
translate:translate(
|
{"label",
|
||||||
Lang, "Access Rules")},
|
translate:translate(
|
||||||
{"var", "access"}],
|
Lang, "Access Rules")},
|
||||||
lists:map(fun(S) ->
|
{"var", "access"}],
|
||||||
{xmlelement, "value", [], [{xmlcdata, S}]}
|
lists:map(fun(S) ->
|
||||||
end,
|
{xmlelement, "value", [], [{xmlcdata, S}]}
|
||||||
string:tokens(
|
end,
|
||||||
lists:flatten(
|
string:tokens(
|
||||||
io_lib:format(
|
lists:flatten(
|
||||||
"~p.",
|
io_lib:format(
|
||||||
[ets:select(config,
|
"~p.",
|
||||||
[{{config, {access, '$1'}, '$2'},
|
[ets:select(config,
|
||||||
[],
|
[{{config, {access, '$1'}, '$2'},
|
||||||
[{{access, '$1', '$2'}}]}])
|
[],
|
||||||
])),
|
[{{access, '$1', '$2'}}]}])
|
||||||
"\n"))
|
])),
|
||||||
}
|
"\n"))
|
||||||
]};
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_form(["config", "remusers"], Lang) ->
|
get_form(["config", "remusers"], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Remove Users")}]},
|
translate:translate(
|
||||||
{xmlelement, "instructions", [],
|
Lang, "Remove Users")}]},
|
||||||
[{xmlcdata,
|
{xmlelement, "instructions", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Choose users to remove")}]}] ++
|
translate:translate(
|
||||||
case catch ejabberd_auth:dirty_get_registered_users() of
|
Lang, "Choose users to remove")}]}] ++
|
||||||
{'EXIT', Reason} ->
|
case catch ejabberd_auth:dirty_get_registered_users() of
|
||||||
[];
|
{'EXIT', Reason} ->
|
||||||
Users ->
|
[];
|
||||||
lists:map(fun(U) ->
|
Users ->
|
||||||
?XFIELD("boolean", U, U, "0")
|
lists:map(fun(U) ->
|
||||||
end, lists:sort(Users))
|
?XFIELD("boolean", U, U, "0")
|
||||||
end
|
end, lists:sort(Users))
|
||||||
};
|
end
|
||||||
|
}]};
|
||||||
|
|
||||||
get_form(_, Lang) ->
|
get_form(_, Lang) ->
|
||||||
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
@ -712,39 +730,45 @@ process_sm_iq(From, To,
|
|||||||
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
|
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
|
||||||
case Type of
|
case Type of
|
||||||
set ->
|
set ->
|
||||||
case xml:get_tag_attr_s("type", SubEl) of
|
XDataEl = find_xdata_el(SubEl),
|
||||||
"cancel" ->
|
case XDataEl of
|
||||||
IQ#iq{type = result,
|
false ->
|
||||||
sub_el = [{xmlelement, "query",
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ACCEPTABLE]};
|
||||||
[{"xmlns", XMLNS}], []}]};
|
{xmlelement, _Name, Attrs, SubEls} ->
|
||||||
"submit" ->
|
case xml:get_attr_s("type", Attrs) of
|
||||||
XData = jlib:parse_xdata_submit(SubEl),
|
"cancel" ->
|
||||||
case XData of
|
IQ#iq{type = result,
|
||||||
invalid ->
|
sub_el = [{xmlelement, "query",
|
||||||
IQ#iq{type = error,
|
[{"xmlns", XMLNS}], []}]};
|
||||||
sub_el = [SubEl, ?ERR_BAD_REQUEST]};
|
"submit" ->
|
||||||
_ ->
|
XData = jlib:parse_xdata_submit(XDataEl),
|
||||||
Node =
|
case XData of
|
||||||
string:tokens(
|
invalid ->
|
||||||
xml:get_tag_attr_s("node", SubEl),
|
|
||||||
"/"),
|
|
||||||
case set_sm_form(
|
|
||||||
User, Node, Lang, XData) of
|
|
||||||
{result, Res} ->
|
|
||||||
IQ#iq{type = result,
|
|
||||||
sub_el =
|
|
||||||
[{xmlelement, "query",
|
|
||||||
[{"xmlns", XMLNS}],
|
|
||||||
Res
|
|
||||||
}]};
|
|
||||||
{error, Error} ->
|
|
||||||
IQ#iq{type = error,
|
IQ#iq{type = error,
|
||||||
sub_el = [SubEl, Error]}
|
sub_el = [SubEl, ?ERR_BAD_REQUEST]};
|
||||||
end
|
_ ->
|
||||||
end;
|
Node =
|
||||||
_ ->
|
string:tokens(
|
||||||
IQ#iq{type = error,
|
xml:get_tag_attr_s("node", SubEl),
|
||||||
sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
|
"/"),
|
||||||
|
case set_sm_form(
|
||||||
|
User, Node, Lang, XData) of
|
||||||
|
{result, Res} ->
|
||||||
|
IQ#iq{type = result,
|
||||||
|
sub_el =
|
||||||
|
[{xmlelement, "query",
|
||||||
|
[{"xmlns", XMLNS}],
|
||||||
|
Res
|
||||||
|
}]};
|
||||||
|
{error, Error} ->
|
||||||
|
IQ#iq{type = error,
|
||||||
|
sub_el = [SubEl, Error]}
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
IQ#iq{type = error,
|
||||||
|
sub_el = [SubEl, ?ERR_BAD_REQUEST]}
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
get ->
|
get ->
|
||||||
Node =
|
Node =
|
||||||
@ -764,34 +788,35 @@ process_sm_iq(From, To,
|
|||||||
|
|
||||||
|
|
||||||
get_sm_form(User, [], Lang) ->
|
get_sm_form(User, [], Lang) ->
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}],
|
||||||
[{xmlcdata,
|
[{xmlelement, "title", [],
|
||||||
translate:translate(
|
[{xmlcdata,
|
||||||
Lang, "Administration of " ++ User)}]},
|
translate:translate(
|
||||||
%{xmlelement, "instructions", [],
|
Lang, "Administration of " ++ User)}]},
|
||||||
% [{xmlcdata,
|
%{xmlelement, "instructions", [],
|
||||||
% translate:translate(
|
% [{xmlcdata,
|
||||||
% Lang, "Choose host name")}]},
|
% translate:translate(
|
||||||
{xmlelement, "field",
|
% Lang, "Choose host name")}]},
|
||||||
[{"type", "list-single"},
|
{xmlelement, "field",
|
||||||
{"label", translate:translate(Lang, "Action on user")},
|
[{"type", "list-single"},
|
||||||
{"var", "action"}],
|
{"label", translate:translate(Lang, "Action on user")},
|
||||||
[{xmlelement, "value", [], [{xmlcdata, "edit"}]},
|
{"var", "action"}],
|
||||||
{xmlelement, "option",
|
[{xmlelement, "value", [], [{xmlcdata, "edit"}]},
|
||||||
[{"label", translate:translate(Lang, "Edit Properties")}],
|
{xmlelement, "option",
|
||||||
[{xmlelement, "value", [], [{xmlcdata, "edit"}]}]},
|
[{"label", translate:translate(Lang, "Edit Properties")}],
|
||||||
{xmlelement, "option",
|
[{xmlelement, "value", [], [{xmlcdata, "edit"}]}]},
|
||||||
[{"label", translate:translate(Lang, "Remove User")}],
|
{xmlelement, "option",
|
||||||
[{xmlelement, "value", [], [{xmlcdata, "remove"}]}]}
|
[{"label", translate:translate(Lang, "Remove User")}],
|
||||||
]},
|
[{xmlelement, "value", [], [{xmlcdata, "remove"}]}]}
|
||||||
?XFIELD("text-private", "Password", "password",
|
]},
|
||||||
ejabberd_auth:get_password_s(User))
|
?XFIELD("text-private", "Password", "password",
|
||||||
%{xmlelement, "field", [{"type", "text-single"},
|
ejabberd_auth:get_password_s(User))
|
||||||
% {"label",
|
%{xmlelement, "field", [{"type", "text-single"},
|
||||||
% translate:translate(Lang, "Host name")},
|
% {"label",
|
||||||
% {"var", "hostname"}],
|
% translate:translate(Lang, "Host name")},
|
||||||
% [{xmlelement, "value", [], [{xmlcdata, ?MYNAME}]}]}
|
% {"var", "hostname"}],
|
||||||
]};
|
% [{xmlelement, "value", [], [{xmlcdata, ?MYNAME}]}]}
|
||||||
|
]}]};
|
||||||
|
|
||||||
get_sm_form(_, _, Lang) ->
|
get_sm_form(_, _, Lang) ->
|
||||||
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
@ -820,3 +845,20 @@ set_sm_form(User, [], Lang, XData) ->
|
|||||||
end;
|
end;
|
||||||
set_sm_form(_, _, Lang, XData) ->
|
set_sm_form(_, _, Lang, XData) ->
|
||||||
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
|
|
||||||
|
find_xdata_el({xmlelement, _Name, _Attrs, SubEls}) ->
|
||||||
|
find_xdata_el1(SubEls).
|
||||||
|
|
||||||
|
find_xdata_el1([]) ->
|
||||||
|
false;
|
||||||
|
|
||||||
|
find_xdata_el1([{xmlelement, Name, Attrs, SubEls} | Els]) ->
|
||||||
|
case xml:get_attr_s("xmlns", Attrs) of
|
||||||
|
?NS_XDATA ->
|
||||||
|
{xmlelement, Name, Attrs, SubEls};
|
||||||
|
_ ->
|
||||||
|
find_xdata_el1(Els)
|
||||||
|
end;
|
||||||
|
|
||||||
|
find_xdata_el1([_ | Els]) ->
|
||||||
|
find_xdata_el1(Els).
|
||||||
|
@ -157,7 +157,7 @@ process_local_iq_info(From, _To, #iq{type = Type, xmlns = XMLNS,
|
|||||||
"query",
|
"query",
|
||||||
[{"xmlns", XMLNS},
|
[{"xmlns", XMLNS},
|
||||||
{"node", SNode}],
|
{"node", SNode}],
|
||||||
[feature_to_xml({?NS_IQDATA})]}]};
|
[feature_to_xml({?NS_EJABBERD_CONFIG})]}]};
|
||||||
{allow, ["running nodes", ENode, "modules"]} ->
|
{allow, ["running nodes", ENode, "modules"]} ->
|
||||||
?EMPTY_INFO_RESULT;
|
?EMPTY_INFO_RESULT;
|
||||||
{allow, ["running nodes", ENode, "modules", _]} ->
|
{allow, ["running nodes", ENode, "modules", _]} ->
|
||||||
@ -165,7 +165,7 @@ process_local_iq_info(From, _To, #iq{type = Type, xmlns = XMLNS,
|
|||||||
sub_el = [{xmlelement, "query",
|
sub_el = [{xmlelement, "query",
|
||||||
[{"xmlns", XMLNS},
|
[{"xmlns", XMLNS},
|
||||||
{"node", SNode}],
|
{"node", SNode}],
|
||||||
[feature_to_xml({?NS_IQDATA})]}]};
|
[feature_to_xml({?NS_EJABBERD_CONFIG})]}]};
|
||||||
{allow, ["running nodes", ENode, "backup"]} ->
|
{allow, ["running nodes", ENode, "backup"]} ->
|
||||||
?EMPTY_INFO_RESULT;
|
?EMPTY_INFO_RESULT;
|
||||||
{allow, ["running nodes", ENode, "backup", _]} ->
|
{allow, ["running nodes", ENode, "backup", _]} ->
|
||||||
@ -173,7 +173,7 @@ process_local_iq_info(From, _To, #iq{type = Type, xmlns = XMLNS,
|
|||||||
sub_el = [{xmlelement, "query",
|
sub_el = [{xmlelement, "query",
|
||||||
[{"xmlns", XMLNS},
|
[{"xmlns", XMLNS},
|
||||||
{"node", SNode}],
|
{"node", SNode}],
|
||||||
[feature_to_xml({?NS_IQDATA})]}]};
|
[feature_to_xml({?NS_EJABBERD_CONFIG})]}]};
|
||||||
{allow, ["running nodes", ENode, "import"]} ->
|
{allow, ["running nodes", ENode, "import"]} ->
|
||||||
?EMPTY_INFO_RESULT;
|
?EMPTY_INFO_RESULT;
|
||||||
{allow, ["running nodes", ENode, "import", _]} ->
|
{allow, ["running nodes", ENode, "import", _]} ->
|
||||||
@ -181,13 +181,13 @@ process_local_iq_info(From, _To, #iq{type = Type, xmlns = XMLNS,
|
|||||||
sub_el = [{xmlelement, "query",
|
sub_el = [{xmlelement, "query",
|
||||||
[{"xmlns", XMLNS},
|
[{"xmlns", XMLNS},
|
||||||
{"node", SNode}],
|
{"node", SNode}],
|
||||||
[feature_to_xml({?NS_IQDATA})]}]};
|
[feature_to_xml({?NS_EJABBERD_CONFIG})]}]};
|
||||||
{allow, ["config", _]} ->
|
{allow, ["config", _]} ->
|
||||||
IQ#iq{type = result,
|
IQ#iq{type = result,
|
||||||
sub_el = [{xmlelement, "query",
|
sub_el = [{xmlelement, "query",
|
||||||
[{"xmlns", XMLNS},
|
[{"xmlns", XMLNS},
|
||||||
{"node", SNode}],
|
{"node", SNode}],
|
||||||
[feature_to_xml({?NS_IQDATA})]}]};
|
[feature_to_xml({?NS_EJABBERD_CONFIG})]}]};
|
||||||
_ ->
|
_ ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}
|
||||||
end
|
end
|
||||||
@ -489,7 +489,7 @@ process_sm_iq_info(From, To, #iq{type = Type, xmlns = XMLNS,
|
|||||||
"" ->
|
"" ->
|
||||||
IQ#iq{type = result,
|
IQ#iq{type = result,
|
||||||
sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}],
|
sub_el = [{xmlelement, "query", [{"xmlns", XMLNS}],
|
||||||
[feature_to_xml({?NS_IQDATA})]}]};
|
[feature_to_xml({?NS_EJABBERD_CONFIG})]}]};
|
||||||
_ ->
|
_ ->
|
||||||
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}
|
IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}
|
||||||
end
|
end
|
||||||
|
@ -358,16 +358,16 @@ set_form(From, [], Lang, XData) ->
|
|||||||
{atomic, _} ->
|
{atomic, _} ->
|
||||||
{result, []};
|
{result, []};
|
||||||
_ ->
|
_ ->
|
||||||
{error, "406", "Not Acceptable"}
|
{error, ?ERR_NOT_ACCEPTABLE}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
{error, "406", "Not Acceptable"}
|
{error, ?ERR_NOT_ACCEPTABLE}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
{error, "406", "Not Acceptable"}
|
{error, ?ERR_NOT_ACCEPTABLE}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
{error, "406", "Not Acceptable"}
|
{error, ?ERR_NOT_ACCEPTABLE}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
config = #config{},
|
config = #config{},
|
||||||
users = ?DICT:new(),
|
users = ?DICT:new(),
|
||||||
affiliations = ?DICT:new(),
|
affiliations = ?DICT:new(),
|
||||||
history = lqueue_new(10),
|
history = lqueue_new(20),
|
||||||
subject = "",
|
subject = "",
|
||||||
subject_author = ""}).
|
subject_author = ""}).
|
||||||
|
|
||||||
@ -831,7 +831,8 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
add_online_user(From, Nick, Role, StateData)),
|
add_online_user(From, Nick, Role, StateData)),
|
||||||
send_new_presence(From, NewState),
|
send_new_presence(From, NewState),
|
||||||
send_existing_presences(From, NewState),
|
send_existing_presences(From, NewState),
|
||||||
case send_history(From, NewState) of
|
Shift = count_stanza_shift(Nick, Els, NewState),
|
||||||
|
case send_history(From, Shift, NewState) of
|
||||||
true ->
|
true ->
|
||||||
ok;
|
ok;
|
||||||
_ ->
|
_ ->
|
||||||
@ -879,7 +880,259 @@ extract_password([{xmlelement, Name, Attrs, SubEls} = El | Els]) ->
|
|||||||
extract_password([_ | Els]) ->
|
extract_password([_ | Els]) ->
|
||||||
extract_password(Els).
|
extract_password(Els).
|
||||||
|
|
||||||
|
count_stanza_shift(Nick, Els, StateData) ->
|
||||||
|
HL = lqueue_to_list(StateData#state.history),
|
||||||
|
Since = extract_history(Els, "since"),
|
||||||
|
Shift0 = case Since of
|
||||||
|
false ->
|
||||||
|
0;
|
||||||
|
_ ->
|
||||||
|
Sin = calendar:datetime_to_gregorian_seconds(Since),
|
||||||
|
count_seconds_shift(Sin, HL)
|
||||||
|
end,
|
||||||
|
Seconds = extract_history(Els, "seconds"),
|
||||||
|
Shift1 = case Seconds of
|
||||||
|
false ->
|
||||||
|
0;
|
||||||
|
_ ->
|
||||||
|
Sec = calendar:datetime_to_gregorian_seconds(
|
||||||
|
calendar:now_to_universal_time(now())) - Seconds,
|
||||||
|
count_seconds_shift(Sec, HL)
|
||||||
|
end,
|
||||||
|
MaxStanzas = extract_history(Els, "maxstanzas"),
|
||||||
|
Shift2 = case MaxStanzas of
|
||||||
|
false ->
|
||||||
|
0;
|
||||||
|
_ ->
|
||||||
|
count_maxstanzas_shift(MaxStanzas, HL)
|
||||||
|
end,
|
||||||
|
MaxChars = extract_history(Els, "maxchars"),
|
||||||
|
Shift3 = case MaxChars of
|
||||||
|
false ->
|
||||||
|
0;
|
||||||
|
_ ->
|
||||||
|
count_maxchars_shift(Nick, MaxChars, HL)
|
||||||
|
end,
|
||||||
|
lists:max([Shift0, Shift1, Shift2, Shift3]).
|
||||||
|
|
||||||
|
count_seconds_shift(Seconds, HistoryList) ->
|
||||||
|
lists:sum(
|
||||||
|
lists:map(
|
||||||
|
fun({_Nick, _Packet, _HaveSubject, TimeStamp, _Size}) ->
|
||||||
|
T = calendar:datetime_to_gregorian_seconds(TimeStamp),
|
||||||
|
if
|
||||||
|
T < Seconds ->
|
||||||
|
1;
|
||||||
|
true ->
|
||||||
|
0
|
||||||
|
end
|
||||||
|
end, HistoryList)).
|
||||||
|
|
||||||
|
count_maxstanzas_shift(MaxStanzas, HistoryList) ->
|
||||||
|
S = length(HistoryList) - MaxStanzas,
|
||||||
|
if
|
||||||
|
S =< 0 ->
|
||||||
|
0;
|
||||||
|
true ->
|
||||||
|
S
|
||||||
|
end.
|
||||||
|
|
||||||
|
count_maxchars_shift(Nick, MaxSize, HistoryList) ->
|
||||||
|
NLen = string:len(Nick) + 1,
|
||||||
|
Sizes = lists:map(
|
||||||
|
fun({_Nick, _Packet, _HaveSubject, _TimeStamp, Size}) ->
|
||||||
|
Size + NLen
|
||||||
|
end, HistoryList),
|
||||||
|
calc_shift(MaxSize, Sizes).
|
||||||
|
|
||||||
|
calc_shift(MaxSize, Sizes) ->
|
||||||
|
Total = lists:sum(Sizes),
|
||||||
|
calc_shift(MaxSize, Total, 0, Sizes).
|
||||||
|
|
||||||
|
calc_shift(_MaxSize, _Size, Shift, []) ->
|
||||||
|
Shift;
|
||||||
|
calc_shift(MaxSize, Size, Shift, [S | TSizes]) ->
|
||||||
|
if
|
||||||
|
MaxSize >= Size ->
|
||||||
|
Shift;
|
||||||
|
true ->
|
||||||
|
calc_shift(MaxSize, Size - S, Shift + 1, TSizes)
|
||||||
|
end.
|
||||||
|
|
||||||
|
extract_history([], Type) ->
|
||||||
|
false;
|
||||||
|
extract_history([{xmlelement, Name, Attrs, SubEls} = El | Els], Type) ->
|
||||||
|
case xml:get_attr_s("xmlns", Attrs) of
|
||||||
|
?NS_MUC ->
|
||||||
|
AttrVal = xml:get_path_s(El,
|
||||||
|
[{elem, "history"}, {attr, Type}]),
|
||||||
|
case Type of
|
||||||
|
"since" ->
|
||||||
|
parse_datetime(AttrVal);
|
||||||
|
_ ->
|
||||||
|
case catch list_to_integer(AttrVal) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
false;
|
||||||
|
IntVal ->
|
||||||
|
if
|
||||||
|
IntVal >= 0 ->
|
||||||
|
IntVal;
|
||||||
|
true ->
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
extract_history(Els, Type)
|
||||||
|
end;
|
||||||
|
extract_history([_ | Els], Type) ->
|
||||||
|
extract_history(Els, Type).
|
||||||
|
|
||||||
|
% JEP-0082
|
||||||
|
% yyyy-mm-ddThh:mm:ss[.sss]{Z|{+|-}hh:mm} -> {{yyyy, mm, dd}, {hh, mm, ss}} (UTC)
|
||||||
|
parse_datetime(TimeStr) ->
|
||||||
|
DateTime = string:tokens(TimeStr, "T"),
|
||||||
|
case DateTime of
|
||||||
|
[Date, Time] ->
|
||||||
|
case parse_date(Date) of
|
||||||
|
false ->
|
||||||
|
false;
|
||||||
|
D ->
|
||||||
|
case parse_time(Time) of
|
||||||
|
false ->
|
||||||
|
false;
|
||||||
|
{T, TZH, TZM} ->
|
||||||
|
S = calendar:datetime_to_gregorian_seconds(
|
||||||
|
{D, T}),
|
||||||
|
calendar:gregorian_seconds_to_datetime(
|
||||||
|
S - TZH * 60 * 60 - TZM * 60 * 30)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
% yyyy-mm-dd
|
||||||
|
parse_date(Date) ->
|
||||||
|
YearMonthDay = string:tokens(Date, "-"),
|
||||||
|
case length(YearMonthDay) of
|
||||||
|
3 ->
|
||||||
|
[Y, M, D] = lists:map(
|
||||||
|
fun(L)->
|
||||||
|
case catch list_to_integer(L) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
false;
|
||||||
|
Int ->
|
||||||
|
Int
|
||||||
|
end
|
||||||
|
end, YearMonthDay),
|
||||||
|
case catch calendar:valid_date(Y, M, D) of
|
||||||
|
true ->
|
||||||
|
{Y, M, D};
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
% hh:mm:ss[.sss]TZD
|
||||||
|
parse_time(Time) ->
|
||||||
|
case string:str(Time, "Z") of
|
||||||
|
0 ->
|
||||||
|
parse_time_with_timezone(Time);
|
||||||
|
_ ->
|
||||||
|
[T | _] = string:tokens(Time, "Z"),
|
||||||
|
case parse_time1(T) of
|
||||||
|
false ->
|
||||||
|
false;
|
||||||
|
TT ->
|
||||||
|
{TT, 0, 0}
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
|
parse_time_with_timezone(Time) ->
|
||||||
|
case string:str(Time, "+") of
|
||||||
|
0 ->
|
||||||
|
case string:str(Time, "-") of
|
||||||
|
0 ->
|
||||||
|
false;
|
||||||
|
_ ->
|
||||||
|
parse_time_with_timezone(Time, "-")
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
parse_time_with_timezone(Time, "+")
|
||||||
|
end.
|
||||||
|
|
||||||
|
parse_time_with_timezone(Time, Delim) ->
|
||||||
|
TTZ = string:tokens(Time, Delim),
|
||||||
|
case TTZ of
|
||||||
|
[T, TZ] ->
|
||||||
|
case parse_timezone(TZ) of
|
||||||
|
false ->
|
||||||
|
false;
|
||||||
|
{TZH, TZM} ->
|
||||||
|
case parse_time1(T) of
|
||||||
|
false ->
|
||||||
|
false;
|
||||||
|
TT ->
|
||||||
|
case Delim of
|
||||||
|
"-" ->
|
||||||
|
{TT, -TZH, -TZM};
|
||||||
|
"+" ->
|
||||||
|
{TT, TZH, TZM};
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
parse_timezone(TZ) ->
|
||||||
|
case string:tokens(TZ, ":") of
|
||||||
|
[H, M] ->
|
||||||
|
case check_list([{H, 12}, {M, 60}]) of
|
||||||
|
{[H, M], true} ->
|
||||||
|
{H, M};
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
parse_time1(Time) ->
|
||||||
|
case string:tokens(Time, ".") of
|
||||||
|
[HMS | _] ->
|
||||||
|
case string:tokens(HMS, ":") of
|
||||||
|
[H, M, S] ->
|
||||||
|
case check_list([{H, 24}, {M, 60}, {S, 60}]) of
|
||||||
|
{[H1, M1, S1], true} ->
|
||||||
|
{H1, M1, S1};
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
check_list(List) ->
|
||||||
|
lists:mapfoldl(
|
||||||
|
fun({L, N}, B)->
|
||||||
|
case catch list_to_integer(L) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
{false, false};
|
||||||
|
Int when (Int >= 0) and (Int =< N) ->
|
||||||
|
{Int, B};
|
||||||
|
_ ->
|
||||||
|
{false, false}
|
||||||
|
end
|
||||||
|
end, true, List).
|
||||||
|
|
||||||
send_update_presence(JID, StateData) ->
|
send_update_presence(JID, StateData) ->
|
||||||
LJID = jlib:jid_tolower(JID),
|
LJID = jlib:jid_tolower(JID),
|
||||||
@ -1087,22 +1340,28 @@ add_message_to_history(FromNick, Packet, StateData) ->
|
|||||||
_ ->
|
_ ->
|
||||||
true
|
true
|
||||||
end,
|
end,
|
||||||
|
TimeStamp = calendar:now_to_universal_time(now()),
|
||||||
TSPacket = append_subtags(Packet,
|
TSPacket = append_subtags(Packet,
|
||||||
[jlib:timestamp_to_xml(
|
[jlib:timestamp_to_xml(TimeStamp)]),
|
||||||
calendar:now_to_universal_time(
|
{xmlelement, Name, Attrs, Els} = TSPacket,
|
||||||
now()))]),
|
SPacket = jlib:replace_from_to(
|
||||||
Q1 = lqueue_in({FromNick, TSPacket, HaveSubject}, StateData#state.history),
|
jlib:jid_replace_resource(StateData#state.jid, FromNick),
|
||||||
|
StateData#state.jid,
|
||||||
|
TSPacket),
|
||||||
|
Size = string:len(xml:element_to_string(SPacket)),
|
||||||
|
Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, TimeStamp, Size},
|
||||||
|
StateData#state.history),
|
||||||
StateData#state{history = Q1}.
|
StateData#state{history = Q1}.
|
||||||
|
|
||||||
send_history(JID, StateData) ->
|
send_history(JID, Shift, StateData) ->
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun({Nick, Packet, HaveSubject}, B) ->
|
fun({Nick, Packet, HaveSubject, _TimeStamp, _Size}, B) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
JID,
|
JID,
|
||||||
Packet),
|
Packet),
|
||||||
B or HaveSubject
|
B or HaveSubject
|
||||||
end, false, lqueue_to_list(StateData#state.history)).
|
end, false, lists:nthtail(Shift, lqueue_to_list(StateData#state.history))).
|
||||||
|
|
||||||
|
|
||||||
send_subject(JID, StateData) ->
|
send_subject(JID, StateData) ->
|
||||||
|
@ -89,7 +89,7 @@ get_local_stats(["running nodes", _], []) ->
|
|||||||
get_local_stats(["running nodes", ENode], Names) ->
|
get_local_stats(["running nodes", ENode], Names) ->
|
||||||
case search_running_node(ENode) of
|
case search_running_node(ENode) of
|
||||||
false ->
|
false ->
|
||||||
{error, "404", "Not Found"};
|
{error, ?ERR_ITEM_NOT_FOUND};
|
||||||
Node ->
|
Node ->
|
||||||
{result,
|
{result,
|
||||||
lists:map(fun(Name) -> get_node_stat(Node, Name) end, Names)}
|
lists:map(fun(Name) -> get_node_stat(Node, Name) end, Names)}
|
||||||
|
Loading…
Reference in New Issue
Block a user