mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
* src/cyrsasl*.erl: SASL support (currently support only PLAIN
mechanism) * src/ejabberd_c2s.erl: Likewise (all): Support for new-style error elements (except old errors "Not Acceptable", "Not Found", "Invalid Namespace" and "Server Connect Failed", so ejabberd may work unstable) SVN Revision: 86
This commit is contained in:
parent
658552d605
commit
f3916bddd2
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
2003-03-09 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
|
* src/cyrsasl*.erl: SASL support (currently support only PLAIN
|
||||||
|
mechanism)
|
||||||
|
* src/ejabberd_c2s.erl: Likewise
|
||||||
|
|
||||||
|
(all): Support for new-style error elements (except old errors
|
||||||
|
"Not Acceptable", "Not Found", "Invalid Namespace" and "Server
|
||||||
|
Connect Failed", so ejabberd may work unstable)
|
||||||
|
|
||||||
2003-03-02 Alexey Shchepin <alexey@sevcom.net>
|
2003-03-02 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
* src/ejabberd_c2s.erl: More correct stream closing
|
* src/ejabberd_c2s.erl: More correct stream closing
|
||||||
|
77
src/cyrsasl.erl
Normal file
77
src/cyrsasl.erl
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
%%% File : cyrsasl.erl
|
||||||
|
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
%%% Purpose : Cyrus SASL-like library
|
||||||
|
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
%%% Id : $Id$
|
||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(cyrsasl).
|
||||||
|
-author('alexey@sevcom.net').
|
||||||
|
-vsn('$Revision$ ').
|
||||||
|
|
||||||
|
-export([start/0,
|
||||||
|
register_mechanism/2,
|
||||||
|
listmech/0,
|
||||||
|
server_new/4,
|
||||||
|
server_start/3,
|
||||||
|
server_step/2]).
|
||||||
|
|
||||||
|
-record(sasl_mechanism, {mechanism, module}).
|
||||||
|
-record(sasl_state, {service, myname, realm, mech_mod, mech_state}).
|
||||||
|
|
||||||
|
-export([behaviour_info/1]).
|
||||||
|
|
||||||
|
behaviour_info(callbacks) ->
|
||||||
|
[{mech_new, 0},
|
||||||
|
{mech_step, 2}];
|
||||||
|
behaviour_info(Other) ->
|
||||||
|
undefined.
|
||||||
|
|
||||||
|
start() ->
|
||||||
|
ets:new(sasl_mechanism, [named_table,
|
||||||
|
public,
|
||||||
|
{keypos, #sasl_mechanism.mechanism}]),
|
||||||
|
cyrsasl_plain:start([]),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
register_mechanism(Mechanism, Module) ->
|
||||||
|
ets:insert(sasl_mechanism, #sasl_mechanism{mechanism = Mechanism,
|
||||||
|
module = Module}).
|
||||||
|
|
||||||
|
listmech() ->
|
||||||
|
ets:select(sasl_mechanism,
|
||||||
|
[{#sasl_mechanism{mechanism = '$1', _ = '_'}, [], ['$1']}]).
|
||||||
|
|
||||||
|
|
||||||
|
server_new(Service, ServerFQDN, UserRealm, SecFlags) ->
|
||||||
|
#sasl_state{service = Service,
|
||||||
|
myname = ServerFQDN,
|
||||||
|
realm = UserRealm}.
|
||||||
|
|
||||||
|
server_start(State, Mech, ClientIn) ->
|
||||||
|
case ets:lookup(sasl_mechanism, Mech) of
|
||||||
|
[#sasl_mechanism{module = Module}] ->
|
||||||
|
MechState = Module:mech_new(),
|
||||||
|
server_step(State#sasl_state{mech_mod = Module,
|
||||||
|
mech_state = MechState},
|
||||||
|
ClientIn);
|
||||||
|
_ ->
|
||||||
|
{error, "454"}
|
||||||
|
end.
|
||||||
|
|
||||||
|
server_step(State, ClientIn) ->
|
||||||
|
Module = State#sasl_state.mech_mod,
|
||||||
|
MechState = State#sasl_state.mech_state,
|
||||||
|
case Module:mech_step(MechState, ClientIn) of
|
||||||
|
{ok, Props} ->
|
||||||
|
{ok, Props};
|
||||||
|
{continue, ServerOut, NewMechState} ->
|
||||||
|
{continue, ServerOut,
|
||||||
|
State#sasl_state{mech_state = NewMechState}};
|
||||||
|
{error, Code} ->
|
||||||
|
{error, Code}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
56
src/cyrsasl_plain.erl
Normal file
56
src/cyrsasl_plain.erl
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
%%% File : cyrsasl_plain.erl
|
||||||
|
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
%%% Purpose : PLAIN SASL mechanism
|
||||||
|
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
%%% Id : $Id$
|
||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(cyrsasl_plain).
|
||||||
|
-author('alexey@sevcom.net').
|
||||||
|
-vsn('$Revision$ ').
|
||||||
|
|
||||||
|
-export([start/1, stop/0, mech_new/0, mech_step/2, parse/1]).
|
||||||
|
|
||||||
|
-behaviour(cyrsasl).
|
||||||
|
%-behaviour(gen_mod).
|
||||||
|
|
||||||
|
start(Opts) ->
|
||||||
|
cyrsasl:register_mechanism("PLAIN", ?MODULE),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
stop() ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
mech_new() ->
|
||||||
|
{ok, []}.
|
||||||
|
|
||||||
|
mech_step(State, ClientIn) ->
|
||||||
|
case parse(ClientIn) of
|
||||||
|
[_, User, Password] ->
|
||||||
|
case ejabberd_auth:check_password(User, Password) of
|
||||||
|
true ->
|
||||||
|
{ok, [{username, User}]};
|
||||||
|
_ ->
|
||||||
|
{error, "454"}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
{error, "454"}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
parse(S) ->
|
||||||
|
parse1(S, "", []).
|
||||||
|
|
||||||
|
parse1([0 | Cs], S, T) ->
|
||||||
|
parse1(Cs, "", [lists:reverse(S) | T]);
|
||||||
|
parse1([C | Cs], S, T) ->
|
||||||
|
parse1(Cs, [C | S], T);
|
||||||
|
%parse1([], [], T) ->
|
||||||
|
% lists:reverse(T);
|
||||||
|
parse1([], S, T) ->
|
||||||
|
lists:reverse([lists:reverse(S) | T]).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -26,6 +26,7 @@ start(normal, Args) ->
|
|||||||
gen_mod:start(),
|
gen_mod:start(),
|
||||||
ejabberd_config:start(),
|
ejabberd_config:start(),
|
||||||
ejabberd_auth:start(),
|
ejabberd_auth:start(),
|
||||||
|
cyrsasl:start(),
|
||||||
Sup = ejabberd_sup:start_link(),
|
Sup = ejabberd_sup:start_link(),
|
||||||
start(),
|
start(),
|
||||||
load_modules(),
|
load_modules(),
|
||||||
|
@ -109,14 +109,8 @@ terminate(Reason, State) ->
|
|||||||
|
|
||||||
check_password(User, Password) ->
|
check_password(User, Password) ->
|
||||||
LUser = jlib:tolower(User),
|
LUser = jlib:tolower(User),
|
||||||
F = fun() ->
|
case catch mnesia:dirty_read({passwd, LUser}) of
|
||||||
case mnesia:read({passwd, LUser}) of
|
[#passwd{password = Password}] ->
|
||||||
[E] ->
|
|
||||||
E#passwd.password
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
case mnesia:transaction(F) of
|
|
||||||
{atomic, Password} ->
|
|
||||||
true;
|
true;
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
|
@ -16,7 +16,12 @@
|
|||||||
-export([start/2, receiver/4, send_text/2, send_element/2]).
|
-export([start/2, receiver/4, send_text/2, send_element/2]).
|
||||||
|
|
||||||
%% gen_fsm callbacks
|
%% gen_fsm callbacks
|
||||||
-export([init/1, wait_for_stream/2, wait_for_auth/2, session_established/2,
|
-export([init/1,
|
||||||
|
wait_for_stream/2,
|
||||||
|
wait_for_auth/2,
|
||||||
|
wait_for_sasl_auth/2,
|
||||||
|
wait_for_resource_auth/2,
|
||||||
|
session_established/2,
|
||||||
handle_event/3,
|
handle_event/3,
|
||||||
handle_sync_event/4,
|
handle_sync_event/4,
|
||||||
code_change/4,
|
code_change/4,
|
||||||
@ -24,11 +29,12 @@
|
|||||||
terminate/3]).
|
terminate/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-define(SETS, gb_sets).
|
-define(SETS, gb_sets).
|
||||||
|
|
||||||
-record(state, {socket, receiver, streamid,
|
-record(state, {socket, receiver, streamid,
|
||||||
|
sasl_state,
|
||||||
access,
|
access,
|
||||||
shaper,
|
shaper,
|
||||||
user = "", server = ?MYNAME, resource = "",
|
user = "", server = ?MYNAME, resource = "",
|
||||||
@ -52,14 +58,16 @@
|
|||||||
"<?xml version='1.0'?>"
|
"<?xml version='1.0'?>"
|
||||||
"<stream:stream xmlns='jabber:client' "
|
"<stream:stream xmlns='jabber:client' "
|
||||||
"xmlns:stream='http://etherx.jabber.org/streams' "
|
"xmlns:stream='http://etherx.jabber.org/streams' "
|
||||||
"id='~s' from='~s'>"
|
"id='~s' from='~s'~s>"
|
||||||
).
|
).
|
||||||
|
|
||||||
-define(STREAM_TRAILER, "</stream:stream>").
|
-define(STREAM_TRAILER, "</stream:stream>").
|
||||||
|
|
||||||
-define(INVALID_NS_ERR, "<stream:error>Invalid Namespace</stream:error>").
|
-define(INVALID_NS_ERR, "<stream:error>Invalid Namespace</stream:error>").
|
||||||
|
%-define(INVALID_XML_ERR,
|
||||||
|
% "<stream:error code='400'>Invalid XML</stream:error>").
|
||||||
-define(INVALID_XML_ERR,
|
-define(INVALID_XML_ERR,
|
||||||
"<stream:error code='400'>Invalid XML</stream:error>").
|
xml:element_to_string(?SERR_XML_NOT_WELL_FORMED)).
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% API
|
%%% API
|
||||||
@ -102,21 +110,48 @@ init([{SockMod, Socket}, Opts]) ->
|
|||||||
%%----------------------------------------------------------------------
|
%%----------------------------------------------------------------------
|
||||||
|
|
||||||
wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
||||||
% TODO
|
case xml:get_attr_s("xmlns:stream", Attrs) of
|
||||||
Header = io_lib:format(?STREAM_HEADER,
|
?NS_STREAM ->
|
||||||
[StateData#state.streamid, ?MYNAME]),
|
case xml:get_attr_s("version", Attrs) of
|
||||||
send_text(StateData#state.socket, Header),
|
"1.0" ->
|
||||||
case lists:keysearch("xmlns:stream", 1, Attrs) of
|
Header = io_lib:format(?STREAM_HEADER,
|
||||||
{value, {"xmlns:stream", "http://etherx.jabber.org/streams"}} ->
|
[StateData#state.streamid,
|
||||||
% TODO
|
?MYNAME,
|
||||||
{next_state, wait_for_auth, StateData};
|
" version='1.0'"]),
|
||||||
|
send_text(StateData#state.socket, Header),
|
||||||
|
SASLState = cyrsasl:server_new("jabber", ?MYNAME, "", []),
|
||||||
|
Mechs = lists:map(fun(S) ->
|
||||||
|
{xmlelement, "mechanism", [],
|
||||||
|
[{xmlcdata, S}]}
|
||||||
|
end, cyrsasl:listmech()),
|
||||||
|
send_element(StateData#state.socket,
|
||||||
|
{xmlelement, "stream:features", [],
|
||||||
|
[{xmlelement, "mechanisms",
|
||||||
|
[{"xmlns", ?NS_SASL_MECHANISMS}],
|
||||||
|
Mechs}]}),
|
||||||
|
{next_state, wait_for_sasl_auth,
|
||||||
|
StateData#state{sasl_state = SASLState}};
|
||||||
|
_ ->
|
||||||
|
Header = io_lib:format(
|
||||||
|
?STREAM_HEADER,
|
||||||
|
[StateData#state.streamid, ?MYNAME, ""]),
|
||||||
|
send_text(StateData#state.socket, Header),
|
||||||
|
{next_state, wait_for_auth, StateData}
|
||||||
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
send_text(StateData#state.socket, ?INVALID_NS_ERR ?STREAM_TRAILER),
|
Header = io_lib:format(
|
||||||
|
?STREAM_HEADER,
|
||||||
|
[StateData#state.streamid, ?MYNAME, ""]),
|
||||||
|
send_text(StateData#state.socket,
|
||||||
|
Header ++ ?INVALID_NS_ERR ?STREAM_TRAILER),
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
wait_for_stream({xmlstreamerror, _}, StateData) ->
|
wait_for_stream({xmlstreamerror, _}, StateData) ->
|
||||||
send_text(StateData#state.socket, ?INVALID_XML_ERR),
|
Header = io_lib:format(?STREAM_HEADER,
|
||||||
|
["none", ?MYNAME, " version='1.0'"]),
|
||||||
|
send_text(StateData#state.socket,
|
||||||
|
Header ++ ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
|
|
||||||
wait_for_stream(closed, StateData) ->
|
wait_for_stream(closed, StateData) ->
|
||||||
@ -125,11 +160,26 @@ wait_for_stream(closed, StateData) ->
|
|||||||
|
|
||||||
wait_for_auth({xmlstreamelement, El}, StateData) ->
|
wait_for_auth({xmlstreamelement, El}, StateData) ->
|
||||||
case is_auth_packet(El) of
|
case is_auth_packet(El) of
|
||||||
{auth, ID, {U, P, D, ""}} ->
|
{auth, ID, get, {"", _, _, _}} ->
|
||||||
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
|
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
|
||||||
send_element(StateData#state.socket, Err),
|
send_element(StateData#state.socket, Err),
|
||||||
{next_state, wait_for_auth, StateData};
|
{next_state, wait_for_auth, StateData};
|
||||||
{auth, ID, {U, P, D, R}} ->
|
{auth, ID, get, {U, _, _, _}} ->
|
||||||
|
{xmlelement, Name, Attrs, Els} = jlib:make_result_iq_reply(El),
|
||||||
|
Res = {xmlelement, Name, Attrs,
|
||||||
|
[{xmlelement, "query", [{"xmlns", ?NS_AUTH}],
|
||||||
|
[{xmlelement, "username", [], [{xmlcdata, U}]},
|
||||||
|
{xmlelement, "password", [], []},
|
||||||
|
{xmlelement, "digest", [], []},
|
||||||
|
{xmlelement, "resource", [], []}
|
||||||
|
]}]},
|
||||||
|
send_element(StateData#state.socket, Res),
|
||||||
|
{next_state, wait_for_auth, StateData};
|
||||||
|
{auth, ID, set, {U, P, D, ""}} ->
|
||||||
|
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
|
||||||
|
send_element(StateData#state.socket, Err),
|
||||||
|
{next_state, wait_for_auth, StateData};
|
||||||
|
{auth, ID, set, {U, P, D, R}} ->
|
||||||
io:format("AUTH: ~p~n", [{U, P, D, R}]),
|
io:format("AUTH: ~p~n", [{U, P, D, R}]),
|
||||||
JID = {U, ?MYNAME, R},
|
JID = {U, ?MYNAME, R},
|
||||||
case acl:match_rule(StateData#state.access, JID) of
|
case acl:match_rule(StateData#state.access, JID) of
|
||||||
@ -149,12 +199,12 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
|
|||||||
pres_t = ?SETS:from_list(Ts)}};
|
pres_t = ?SETS:from_list(Ts)}};
|
||||||
_ ->
|
_ ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
El, "401", "Unauthorized"),
|
El, ?ERR_FORBIDDEN),
|
||||||
send_element(StateData#state.socket, Err),
|
send_element(StateData#state.socket, Err),
|
||||||
{next_state, wait_for_auth, StateData}
|
{next_state, wait_for_auth, StateData}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Err = jlib:make_error_reply(El, "405", "Not Allowed"),
|
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
|
||||||
send_element(StateData#state.socket, Err),
|
send_element(StateData#state.socket, Err),
|
||||||
{next_state, wait_for_auth, StateData}
|
{next_state, wait_for_auth, StateData}
|
||||||
end;
|
end;
|
||||||
@ -180,12 +230,152 @@ wait_for_auth({xmlstreamend, Name}, StateData) ->
|
|||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
|
|
||||||
wait_for_auth({xmlstreamerror, _}, StateData) ->
|
wait_for_auth({xmlstreamerror, _}, StateData) ->
|
||||||
send_text(StateData#state.socket, ?INVALID_XML_ERR ?STREAM_TRAILER),
|
send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
|
|
||||||
wait_for_auth(closed, StateData) ->
|
wait_for_auth(closed, StateData) ->
|
||||||
{stop, normal, StateData}.
|
{stop, normal, StateData}.
|
||||||
|
|
||||||
|
|
||||||
|
wait_for_sasl_auth({xmlstreamelement, El}, StateData) ->
|
||||||
|
{xmlelement, Name, Attrs, Els} = El,
|
||||||
|
case {xml:get_attr_s("xmlns", Attrs), Name} of
|
||||||
|
{?NS_SASL_MECHANISMS, "auth"} ->
|
||||||
|
Mech = xml:get_attr_s("mechanism", Attrs),
|
||||||
|
ClientIn = jlib:decode_base64(xml:get_cdata(Els)),
|
||||||
|
case cyrsasl:server_start(StateData#state.sasl_state,
|
||||||
|
Mech,
|
||||||
|
ClientIn) of
|
||||||
|
{ok, Props} ->
|
||||||
|
send_element(StateData#state.socket,
|
||||||
|
{xmlelement, "success",
|
||||||
|
[{"xmlns", ?NS_SASL_MECHANISMS}], []}),
|
||||||
|
{next_state, wait_for_resource_auth,
|
||||||
|
StateData#state{user = xml:get_attr_s(username, Props)}};
|
||||||
|
{continue, ServerOut, NewSASLState} ->
|
||||||
|
send_element(StateData#state.socket,
|
||||||
|
{xmlelement, "challenge",
|
||||||
|
[{"xmlns", ?NS_SASL_MECHANISMS}],
|
||||||
|
[{xmlcdata,
|
||||||
|
jlib:encode_base64(ServerOut)}]}),
|
||||||
|
{next_state, wait_for_sasl_response, StateData};
|
||||||
|
{error, Code} ->
|
||||||
|
send_element(StateData#state.socket,
|
||||||
|
{xmlelement, "failure",
|
||||||
|
[{"xmlns", ?NS_SASL_MECHANISMS},
|
||||||
|
{"code", Code}],
|
||||||
|
[]}),
|
||||||
|
{next_state, wait_for_sasl_auth, StateData}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
case jlib:iq_query_info(El) of
|
||||||
|
{iq, ID, Type, ?NS_REGISTER, SubEl} ->
|
||||||
|
ResIQ = mod_register:process_iq(
|
||||||
|
{"", "", ""}, {"", ?MYNAME, ""},
|
||||||
|
{iq, ID, Type, ?NS_REGISTER, SubEl}),
|
||||||
|
Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
|
||||||
|
{"", "", ""},
|
||||||
|
jlib:iq_to_xml(ResIQ)),
|
||||||
|
Res = jlib:remove_attr("to", Res1),
|
||||||
|
send_element(StateData#state.socket, Res),
|
||||||
|
{next_state, wait_for_sasl_auth, StateData};
|
||||||
|
_ ->
|
||||||
|
{next_state, wait_for_sasl_auth, StateData}
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
wait_for_sasl_auth({xmlstreamend, Name}, StateData) ->
|
||||||
|
send_text(StateData#state.socket, ?STREAM_TRAILER),
|
||||||
|
{stop, normal, StateData};
|
||||||
|
|
||||||
|
wait_for_sasl_auth({xmlstreamerror, _}, StateData) ->
|
||||||
|
send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||||
|
{stop, normal, StateData};
|
||||||
|
|
||||||
|
wait_for_sasl_auth(closed, StateData) ->
|
||||||
|
{stop, normal, StateData}.
|
||||||
|
|
||||||
|
|
||||||
|
wait_for_resource_auth({xmlstreamelement, El}, StateData) ->
|
||||||
|
case is_auth_packet(El) of
|
||||||
|
{auth, ID, get, {"", _, _, _}} ->
|
||||||
|
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
|
||||||
|
send_element(StateData#state.socket, Err),
|
||||||
|
{next_state, wait_for_resource_auth, StateData};
|
||||||
|
{auth, ID, get, {U, _, _, _}} ->
|
||||||
|
{xmlelement, Name, Attrs, Els} = jlib:make_result_iq_reply(El),
|
||||||
|
Res = {xmlelement, Name, Attrs,
|
||||||
|
[{xmlelement, "query", [{"xmlns", ?NS_AUTH}],
|
||||||
|
[{xmlelement, "username", [],
|
||||||
|
[{xmlcdata, StateData#state.user}]},
|
||||||
|
{xmlelement, "resource", [], []}
|
||||||
|
]}]},
|
||||||
|
send_element(StateData#state.socket, Res),
|
||||||
|
{next_state, wait_for_resource_auth, StateData};
|
||||||
|
{auth, ID, set, {U, _, _, ""}} ->
|
||||||
|
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
|
||||||
|
send_element(StateData#state.socket, Err),
|
||||||
|
{next_state, wait_for_resource_auth, StateData};
|
||||||
|
{auth, ID, set, {U, _, _, R}} ->
|
||||||
|
case StateData#state.user of
|
||||||
|
U ->
|
||||||
|
io:format("SASLAUTH: ~p~n", [{U, R}]),
|
||||||
|
JID = {U, ?MYNAME, R},
|
||||||
|
case acl:match_rule(StateData#state.access, JID) of
|
||||||
|
allow ->
|
||||||
|
ejabberd_sm:open_session(U, R),
|
||||||
|
Res = jlib:make_result_iq_reply(El),
|
||||||
|
send_element(StateData#state.socket, Res),
|
||||||
|
change_shaper(StateData, JID),
|
||||||
|
{Fs, Ts} = mod_roster:get_subscription_lists(U),
|
||||||
|
{next_state, session_established,
|
||||||
|
StateData#state{user = U,
|
||||||
|
resource = R,
|
||||||
|
pres_f = ?SETS:from_list(Fs),
|
||||||
|
pres_t = ?SETS:from_list(Ts)}};
|
||||||
|
_ ->
|
||||||
|
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
|
||||||
|
send_element(StateData#state.socket, Err),
|
||||||
|
{next_state, wait_for_resource_auth, StateData}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
|
||||||
|
send_element(StateData#state.socket, Err),
|
||||||
|
{next_state, wait_for_resource_auth, StateData}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
case jlib:iq_query_info(El) of
|
||||||
|
{iq, ID, Type, ?NS_REGISTER, SubEl} ->
|
||||||
|
ResIQ = mod_register:process_iq(
|
||||||
|
{"", "", ""}, {"", ?MYNAME, ""},
|
||||||
|
{iq, ID, Type, ?NS_REGISTER, SubEl}),
|
||||||
|
Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
|
||||||
|
{"", "", ""},
|
||||||
|
jlib:iq_to_xml(ResIQ)),
|
||||||
|
Res = jlib:remove_attr("to", Res1),
|
||||||
|
send_element(StateData#state.socket, Res),
|
||||||
|
{next_state, wait_for_resource_auth, StateData};
|
||||||
|
_ ->
|
||||||
|
{next_state, wait_for_resource_auth, StateData}
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
wait_for_resource_auth({xmlstreamend, Name}, StateData) ->
|
||||||
|
send_text(StateData#state.socket, ?STREAM_TRAILER),
|
||||||
|
{stop, normal, StateData};
|
||||||
|
|
||||||
|
wait_for_resource_auth({xmlstreamerror, _}, StateData) ->
|
||||||
|
send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||||
|
{stop, normal, StateData};
|
||||||
|
|
||||||
|
wait_for_resource_auth(closed, StateData) ->
|
||||||
|
{stop, normal, StateData}.
|
||||||
|
|
||||||
|
|
||||||
|
% TODO: wait_for_sasl_response
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
session_established({xmlstreamelement, El}, StateData) ->
|
session_established({xmlstreamelement, El}, StateData) ->
|
||||||
{xmlelement, Name, Attrs, Els} = El,
|
{xmlelement, Name, Attrs, Els} = El,
|
||||||
Server = StateData#state.server,
|
Server = StateData#state.server,
|
||||||
@ -227,7 +417,7 @@ session_established({xmlstreamend, Name}, StateData) ->
|
|||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
|
|
||||||
session_established({xmlstreamerror, _}, StateData) ->
|
session_established({xmlstreamerror, _}, StateData) ->
|
||||||
send_text(StateData#state.socket, ?INVALID_XML_ERR ?STREAM_TRAILER),
|
send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
|
|
||||||
session_established(closed, StateData) ->
|
session_established(closed, StateData) ->
|
||||||
@ -427,7 +617,7 @@ is_auth_packet(El) ->
|
|||||||
case jlib:iq_query_info(El) of
|
case jlib:iq_query_info(El) of
|
||||||
{iq, ID, Type, ?NS_AUTH, SubEl} ->
|
{iq, ID, Type, ?NS_AUTH, SubEl} ->
|
||||||
{xmlelement, _, _, Els} = SubEl,
|
{xmlelement, _, _, Els} = SubEl,
|
||||||
{auth, ID,
|
{auth, ID, Type,
|
||||||
get_auth_tags(Els, "", "", "", "")};
|
get_auth_tags(Els, "", "", "", "")};
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
]).
|
]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(state, {mydomain, iqtable}).
|
-record(state, {mydomain, iqtable}).
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ do_route(State, From, To, Packet) ->
|
|||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
{"", _, _} ->
|
{"", _, _} ->
|
||||||
Err = jlib:make_error_reply(Packet, "404", "Not Found"),
|
Err = jlib:make_error_reply(Packet, ?ERR_JID_NOT_FOUND),
|
||||||
ejabberd_router ! {route,
|
ejabberd_router ! {route,
|
||||||
{"", State#state.mydomain, ""}, From, Err},
|
{"", State#state.mydomain, ""}, From, Err},
|
||||||
ok;
|
ok;
|
||||||
@ -116,13 +117,12 @@ process_iq(State, From, To, Packet) ->
|
|||||||
Err}
|
Err}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
% TODO
|
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
reply ->
|
reply ->
|
||||||
ok;
|
ok;
|
||||||
_ ->
|
_ ->
|
||||||
Err = jlib:make_error_reply(Packet, "400", "Bad Request"),
|
Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST),
|
||||||
ejabberd_router ! {route,
|
ejabberd_router ! {route,
|
||||||
{"", State#state.mydomain, ""}, From, Err},
|
{"", State#state.mydomain, ""}, From, Err},
|
||||||
ok
|
ok
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
terminate/3]).
|
terminate/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(state, {socket, pid,
|
-record(state, {socket, pid,
|
||||||
user = "", server = ?MYNAME, resource = ""
|
user = "", server = ?MYNAME, resource = ""
|
||||||
|
82
src/jlib.erl
82
src/jlib.erl
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
-export([make_result_iq_reply/1,
|
-export([make_result_iq_reply/1,
|
||||||
make_error_reply/3,
|
make_error_reply/3,
|
||||||
|
make_error_reply/2,
|
||||||
make_error_element/2,
|
make_error_element/2,
|
||||||
make_correct_from_to_attrs/3,
|
make_correct_from_to_attrs/3,
|
||||||
replace_from_to_attrs/3,
|
replace_from_to_attrs/3,
|
||||||
@ -29,9 +30,11 @@
|
|||||||
iq_to_xml/1,
|
iq_to_xml/1,
|
||||||
parse_xdata_submit/1,
|
parse_xdata_submit/1,
|
||||||
timestamp_to_iso/1,
|
timestamp_to_iso/1,
|
||||||
timestamp_to_xml/1]).
|
timestamp_to_xml/1,
|
||||||
|
decode_base64/1,
|
||||||
|
encode_base64/1]).
|
||||||
|
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
%send_iq(From, To, ID, SubTags) ->
|
%send_iq(From, To, ID, SubTags) ->
|
||||||
% ok.
|
% ok.
|
||||||
@ -67,6 +70,10 @@ make_error_reply({xmlelement, Name, Attrs, SubTags}, Code, Desc) ->
|
|||||||
[{"code", Code}],
|
[{"code", Code}],
|
||||||
[{xmlcdata, Desc}]}]}.
|
[{xmlcdata, Desc}]}]}.
|
||||||
|
|
||||||
|
make_error_reply({xmlelement, Name, Attrs, SubTags}, Error) ->
|
||||||
|
NewAttrs = make_error_reply_attrs(Attrs),
|
||||||
|
{xmlelement, Name, NewAttrs, SubTags ++ [Error]}.
|
||||||
|
|
||||||
make_error_reply_attrs(Attrs) ->
|
make_error_reply_attrs(Attrs) ->
|
||||||
To = xml:get_attr("to", Attrs),
|
To = xml:get_attr("to", Attrs),
|
||||||
From = xml:get_attr("from", Attrs),
|
From = xml:get_attr("from", Attrs),
|
||||||
@ -362,3 +369,74 @@ timestamp_to_xml({{Year, Month, Day}, {Hour, Minute, Second}}) ->
|
|||||||
[Year, Month, Day, Hour, Minute, Second]))}],
|
[Year, Month, Day, Hour, Minute, Second]))}],
|
||||||
[]}.
|
[]}.
|
||||||
|
|
||||||
|
|
||||||
|
%
|
||||||
|
% Base64 stuff (based on httpd_util.erl)
|
||||||
|
%
|
||||||
|
|
||||||
|
decode_base64(S) ->
|
||||||
|
decode1_base64([C || C <- S,
|
||||||
|
C /= $ ,
|
||||||
|
C /= $\t,
|
||||||
|
C /= $\n,
|
||||||
|
C /= $\r]).
|
||||||
|
|
||||||
|
decode1_base64([]) ->
|
||||||
|
[];
|
||||||
|
decode1_base64([Sextet1,Sextet2,$=,$=|Rest]) ->
|
||||||
|
Bits2x6=
|
||||||
|
(d(Sextet1) bsl 18) bor
|
||||||
|
(d(Sextet2) bsl 12),
|
||||||
|
Octet1=Bits2x6 bsr 16,
|
||||||
|
[Octet1|decode_base64(Rest)];
|
||||||
|
decode1_base64([Sextet1,Sextet2,Sextet3,$=|Rest]) ->
|
||||||
|
Bits3x6=
|
||||||
|
(d(Sextet1) bsl 18) bor
|
||||||
|
(d(Sextet2) bsl 12) bor
|
||||||
|
(d(Sextet3) bsl 6),
|
||||||
|
Octet1=Bits3x6 bsr 16,
|
||||||
|
Octet2=(Bits3x6 bsr 8) band 16#ff,
|
||||||
|
[Octet1,Octet2|decode_base64(Rest)];
|
||||||
|
decode1_base64([Sextet1,Sextet2,Sextet3,Sextet4|Rest]) ->
|
||||||
|
Bits4x6=
|
||||||
|
(d(Sextet1) bsl 18) bor
|
||||||
|
(d(Sextet2) bsl 12) bor
|
||||||
|
(d(Sextet3) bsl 6) bor
|
||||||
|
d(Sextet4),
|
||||||
|
Octet1=Bits4x6 bsr 16,
|
||||||
|
Octet2=(Bits4x6 bsr 8) band 16#ff,
|
||||||
|
Octet3=Bits4x6 band 16#ff,
|
||||||
|
[Octet1,Octet2,Octet3|decode_base64(Rest)];
|
||||||
|
decode1_base64(CatchAll) ->
|
||||||
|
"".
|
||||||
|
|
||||||
|
d(X) when X >= $A, X =<$Z ->
|
||||||
|
X-65;
|
||||||
|
d(X) when X >= $a, X =<$z ->
|
||||||
|
X-71;
|
||||||
|
d(X) when X >= $0, X =<$9 ->
|
||||||
|
X+4;
|
||||||
|
d($+) -> 62;
|
||||||
|
d($/) -> 63;
|
||||||
|
d(_) -> 63.
|
||||||
|
|
||||||
|
|
||||||
|
encode_base64([]) ->
|
||||||
|
[];
|
||||||
|
encode_base64([A]) ->
|
||||||
|
[e(A bsr 2), e((A band 3) bsl 4), $=, $=];
|
||||||
|
encode_base64([A,B]) ->
|
||||||
|
[e(A bsr 2), e(((A band 3) bsl 4) bor (B bsr 4)), e((B band 15) bsl 2), $=];
|
||||||
|
encode_base64([A,B,C|Ls]) ->
|
||||||
|
encode_base64_do(A,B,C, Ls).
|
||||||
|
encode_base64_do(A,B,C, Rest) ->
|
||||||
|
BB = (A bsl 16) bor (B bsl 8) bor C,
|
||||||
|
[e(BB bsr 18), e((BB bsr 12) band 63),
|
||||||
|
e((BB bsr 6) band 63), e(BB band 63)|encode_base64(Rest)].
|
||||||
|
|
||||||
|
e(X) when X >= 0, X < 26 -> X+65;
|
||||||
|
e(X) when X>25, X<52 -> X+71;
|
||||||
|
e(X) when X>51, X<62 -> X-4;
|
||||||
|
e(62) -> $+;
|
||||||
|
e(63) -> $/;
|
||||||
|
e(X) -> exit({bad_encode_base64_token, X}).
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
process_sm_iq/3]).
|
process_sm_iq/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
|
|
||||||
start(Opts) ->
|
start(Opts) ->
|
||||||
@ -37,9 +37,7 @@ stop() ->
|
|||||||
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
||||||
case acl:match_rule(configure, From) of
|
case acl:match_rule(configure, From) of
|
||||||
deny ->
|
deny ->
|
||||||
{iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
|
{iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
|
||||||
[{"code", "405"}],
|
|
||||||
[{xmlcdata, "Not Allowed"}]}]};
|
|
||||||
allow ->
|
allow ->
|
||||||
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
|
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
|
||||||
case Type of
|
case Type of
|
||||||
@ -68,11 +66,9 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
[{"xmlns", XMLNS}],
|
[{"xmlns", XMLNS}],
|
||||||
Res
|
Res
|
||||||
}]};
|
}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
@ -90,11 +86,9 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
[{xmlelement, "query", [{"xmlns", XMLNS}],
|
[{xmlelement, "query", [{"xmlns", XMLNS}],
|
||||||
Res
|
Res
|
||||||
}]};
|
}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
@ -140,7 +134,7 @@ get_form(["running nodes", ENode, "DB"], Lang) ->
|
|||||||
Node ->
|
Node ->
|
||||||
case rpc:call(Node, mnesia, system_info, [tables]) of
|
case rpc:call(Node, mnesia, system_info, [tables]) of
|
||||||
{badrpc, Reason} ->
|
{badrpc, Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
Tables ->
|
Tables ->
|
||||||
STables = lists:sort(Tables),
|
STables = lists:sort(Tables),
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "title", [],
|
||||||
@ -174,7 +168,7 @@ get_form(["running nodes", ENode, "modules", "stop"], Lang) ->
|
|||||||
Node ->
|
Node ->
|
||||||
case rpc:call(Node, gen_mod, loaded_modules, []) of
|
case rpc:call(Node, gen_mod, loaded_modules, []) of
|
||||||
{badrpc, Reason} ->
|
{badrpc, Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
Modules ->
|
Modules ->
|
||||||
SModules = lists:sort(Modules),
|
SModules = lists:sort(Modules),
|
||||||
{result, [{xmlelement, "title", [],
|
{result, [{xmlelement, "title", [],
|
||||||
@ -390,7 +384,7 @@ get_form(["config", "remusers"], Lang) ->
|
|||||||
};
|
};
|
||||||
|
|
||||||
get_form(_, Lang) ->
|
get_form(_, Lang) ->
|
||||||
{error, "503", "Service Unavailable"}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -493,9 +487,9 @@ set_form(["running nodes", ENode, "backup", "backup"], Lang, XData) ->
|
|||||||
{value, {_, [String]}} ->
|
{value, {_, [String]}} ->
|
||||||
case rpc:call(Node, mnesia, backup, [String]) of
|
case rpc:call(Node, mnesia, backup, [String]) of
|
||||||
{badrpc, Reason} ->
|
{badrpc, Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
_ ->
|
_ ->
|
||||||
{result, []}
|
{result, []}
|
||||||
end;
|
end;
|
||||||
@ -517,9 +511,9 @@ set_form(["running nodes", ENode, "backup", "restore"], Lang, XData) ->
|
|||||||
case rpc:call(Node, mnesia, restore,
|
case rpc:call(Node, mnesia, restore,
|
||||||
[String, [{default_op, keep_tables}]]) of
|
[String, [{default_op, keep_tables}]]) of
|
||||||
{badrpc, Reason} ->
|
{badrpc, Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
_ ->
|
_ ->
|
||||||
{result, []}
|
{result, []}
|
||||||
end;
|
end;
|
||||||
@ -540,9 +534,9 @@ set_form(["running nodes", ENode, "backup", "textfile"], Lang, XData) ->
|
|||||||
{value, {_, [String]}} ->
|
{value, {_, [String]}} ->
|
||||||
case rpc:call(Node, mnesia, dump_to_textfile, [String]) of
|
case rpc:call(Node, mnesia, dump_to_textfile, [String]) of
|
||||||
{badrpc, Reason} ->
|
{badrpc, Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
_ ->
|
_ ->
|
||||||
{result, []}
|
{result, []}
|
||||||
end;
|
end;
|
||||||
@ -689,7 +683,7 @@ set_form(["config", "remusers"], Lang, XData) ->
|
|||||||
{result, []};
|
{result, []};
|
||||||
|
|
||||||
set_form(_, Lang, XData) ->
|
set_form(_, Lang, XData) ->
|
||||||
{error, "503", "Service Unavailable"}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -744,11 +738,9 @@ process_sm_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
[{"xmlns", XMLNS}],
|
[{"xmlns", XMLNS}],
|
||||||
Res
|
Res
|
||||||
}]};
|
}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
@ -766,11 +758,9 @@ process_sm_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
[{xmlelement, "query", [{"xmlns", XMLNS}],
|
[{xmlelement, "query", [{"xmlns", XMLNS}],
|
||||||
Res
|
Res
|
||||||
}]};
|
}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
@ -807,8 +797,8 @@ get_sm_form(User, [], Lang) ->
|
|||||||
]};
|
]};
|
||||||
|
|
||||||
get_sm_form(_, _, Lang) ->
|
get_sm_form(_, _, Lang) ->
|
||||||
{error, "503", "Service Unavailable"}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
|
|
||||||
|
|
||||||
set_sm_form(_, _, Lang, XData) ->
|
set_sm_form(_, _, Lang, XData) ->
|
||||||
{error, "503", "Service Unavailable"}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
unregister_feature/1]).
|
unregister_feature/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-define(EMPTY_INFO_RESULT,
|
-define(EMPTY_INFO_RESULT,
|
||||||
{iq, ID, result, XMLNS, [{xmlelement, "query",
|
{iq, ID, result, XMLNS, [{xmlelement, "query",
|
||||||
@ -62,9 +62,7 @@ process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
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 ->
|
||||||
{iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
|
{iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
|
||||||
[{"code", "405"}],
|
|
||||||
[{xmlcdata, "Not Allowed"}]}]};
|
|
||||||
get ->
|
get ->
|
||||||
Node = string:tokens(xml:get_tag_attr_s("node", SubEl), "/"),
|
Node = string:tokens(xml:get_tag_attr_s("node", SubEl), "/"),
|
||||||
|
|
||||||
@ -74,11 +72,9 @@ process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
[{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
|
[{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
|
||||||
Res
|
Res
|
||||||
}]};
|
}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -86,9 +82,7 @@ process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
||||||
case Type of
|
case Type of
|
||||||
set ->
|
set ->
|
||||||
{iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
|
{iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
|
||||||
[{"code", "405"}],
|
|
||||||
[{xmlcdata, "Not Allowed"}]}]};
|
|
||||||
get ->
|
get ->
|
||||||
case string:tokens(xml:get_tag_attr_s("node", SubEl), "/") of
|
case string:tokens(xml:get_tag_attr_s("node", SubEl), "/") of
|
||||||
[] ->
|
[] ->
|
||||||
@ -149,9 +143,7 @@ process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
[feature_to_xml({?NS_IQDATA})]}]};
|
[feature_to_xml({?NS_IQDATA})]}]};
|
||||||
_ ->
|
_ ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}
|
||||||
[{"code", "501"}],
|
|
||||||
[{xmlcdata, "Not Implemented"}]}]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -204,7 +196,7 @@ get_local_items(["all users"], Server, Lang) ->
|
|||||||
get_local_items(["all users", [$@ | Diap]], Server, Lang) ->
|
get_local_items(["all users", [$@ | Diap]], Server, Lang) ->
|
||||||
case catch ejabberd_auth:dirty_get_registered_users() of
|
case catch ejabberd_auth:dirty_get_registered_users() of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
?ERR_INTERNAL_SERVER_ERROR;
|
||||||
Users ->
|
Users ->
|
||||||
SUsers = lists:sort(Users),
|
SUsers = lists:sort(Users),
|
||||||
case catch begin
|
case catch begin
|
||||||
@ -219,7 +211,8 @@ get_local_items(["all users", [$@ | Diap]], Server, Lang) ->
|
|||||||
end, Sub)
|
end, Sub)
|
||||||
end of
|
end of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
{error, "406", "Not Acceptable"};
|
% TODO: must be "not acceptable"
|
||||||
|
?ERR_BAD_REQUEST;
|
||||||
Res ->
|
Res ->
|
||||||
{result, Res}
|
{result, Res}
|
||||||
end
|
end
|
||||||
@ -279,7 +272,7 @@ get_local_items(["running nodes", ENode, "import", _], Server, Lang) ->
|
|||||||
{result, []};
|
{result, []};
|
||||||
|
|
||||||
get_local_items(_, _, _) ->
|
get_local_items(_, _, _) ->
|
||||||
{error, "501", "Not Implemented"}.
|
{error, ?ERR_FEATURE_NOT_IMPLEMENTED}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -413,9 +406,7 @@ process_sm_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
{User, _, _} = To,
|
{User, _, _} = To,
|
||||||
case Type of
|
case Type of
|
||||||
set ->
|
set ->
|
||||||
{iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
|
{iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
|
||||||
[{"code", "405"}],
|
|
||||||
[{xmlcdata, "Not Allowed"}]}]};
|
|
||||||
get ->
|
get ->
|
||||||
case xml:get_tag_attr_s("node", SubEl) of
|
case xml:get_tag_attr_s("node", SubEl) of
|
||||||
"" ->
|
"" ->
|
||||||
@ -425,9 +416,7 @@ process_sm_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
}]};
|
}]};
|
||||||
_ ->
|
_ ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}
|
||||||
[{"code", "501"}],
|
|
||||||
[{xmlcdata, "Not Implemented"}]}]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -435,9 +424,7 @@ process_sm_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
process_sm_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
process_sm_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
||||||
case Type of
|
case Type of
|
||||||
set ->
|
set ->
|
||||||
{iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
|
{iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
|
||||||
[{"code", "405"}],
|
|
||||||
[{xmlcdata, "Not Allowed"}]}]};
|
|
||||||
get ->
|
get ->
|
||||||
case xml:get_tag_attr_s("node", SubEl) of
|
case xml:get_tag_attr_s("node", SubEl) of
|
||||||
"" ->
|
"" ->
|
||||||
@ -446,9 +433,7 @@ process_sm_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
[feature_to_xml({?NS_IQDATA})]}]};
|
[feature_to_xml({?NS_IQDATA})]}]};
|
||||||
_ ->
|
_ ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}
|
||||||
[{"code", "501"}],
|
|
||||||
[{xmlcdata, "Not Implemented"}]}]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
-export([start/1, init/1, stop/0]).
|
-export([start/1, init/1, stop/0]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
get_user_and_encoding/2]).
|
get_user_and_encoding/2]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-define(DEFAULT_IRC_ENCODING, "koi8-r").
|
-define(DEFAULT_IRC_ENCODING, "koi8-r").
|
||||||
|
|
||||||
@ -200,18 +200,14 @@ process_iq_data(From, To, ID, XMLNS, Type, SubEl) ->
|
|||||||
[{"xmlns", XMLNS}],
|
[{"xmlns", XMLNS}],
|
||||||
Res
|
Res
|
||||||
}]};
|
}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, ?ERR_NOT_ALLOWED]}
|
||||||
[{"code", "405"}],
|
|
||||||
[{xmlcdata, "Not Allowed"}]}]}
|
|
||||||
end;
|
end;
|
||||||
get ->
|
get ->
|
||||||
Node =
|
Node =
|
||||||
@ -222,11 +218,9 @@ process_iq_data(From, To, ID, XMLNS, Type, SubEl) ->
|
|||||||
[{xmlelement, "query", [{"xmlns", XMLNS}],
|
[{xmlelement, "query", [{"xmlns", XMLNS}],
|
||||||
Res
|
Res
|
||||||
}]};
|
}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -238,7 +232,7 @@ get_form(From, [], Lang) ->
|
|||||||
Customs =
|
Customs =
|
||||||
case catch mnesia:dirty_read({irc_custom, {LUser, LServer}}) of
|
case catch mnesia:dirty_read({irc_custom, {LUser, LServer}}) of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
{error, "500", "Internal Server Error"};
|
{error, ?ERR_INTERNAL_SERVER_ERROR};
|
||||||
[] ->
|
[] ->
|
||||||
{User, []};
|
{User, []};
|
||||||
[#irc_custom{data = Data}] ->
|
[#irc_custom{data = Data}] ->
|
||||||
@ -302,7 +296,7 @@ get_form(From, [], Lang) ->
|
|||||||
|
|
||||||
|
|
||||||
get_form(_, _, Lang) ->
|
get_form(_, _, Lang) ->
|
||||||
{error, "503", "Service Unavailable"}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -347,7 +341,7 @@ set_form(From, [], Lang, XData) ->
|
|||||||
|
|
||||||
|
|
||||||
set_form(_, _, Lang, XData) ->
|
set_form(_, _, Lang, XData) ->
|
||||||
{error, "503", "Service Unavailable"}.
|
{error, ?ERR_SERVICE_UNAVAILABLE}.
|
||||||
|
|
||||||
|
|
||||||
get_user_and_encoding(From, IRCServer) ->
|
get_user_and_encoding(From, IRCServer) ->
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
code_change/4]).
|
code_change/4]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-define(SETS, gb_sets).
|
-define(SETS, gb_sets).
|
||||||
|
|
||||||
@ -285,7 +285,7 @@ handle_info({route_chan, Channel, Resource,
|
|||||||
ID, XMLNS, Type, SubEl);
|
ID, XMLNS, Type, SubEl);
|
||||||
_ ->
|
_ ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
El, "503", "Service Unavailable"),
|
El, ?ERR_SERVICE_UNAVAILABLE),
|
||||||
ejabberd_router:route(To, From, Err)
|
ejabberd_router:route(To, From, Err)
|
||||||
end,
|
end,
|
||||||
{next_state, StateName, StateData};
|
{next_state, StateName, StateData};
|
||||||
@ -835,11 +835,9 @@ iq_admin(StateData, Channel, From, To, ID, XMLNS, Type, SubEl) ->
|
|||||||
[{"xmlns", XMLNS}],
|
[{"xmlns", XMLNS}],
|
||||||
ResEls
|
ResEls
|
||||||
}]};
|
}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end,
|
end,
|
||||||
ejabberd_router:route(To, From,
|
ejabberd_router:route(To, From,
|
||||||
jlib:iq_to_xml(ResIQ));
|
jlib:iq_to_xml(ResIQ));
|
||||||
@ -852,7 +850,7 @@ iq_admin(StateData, Channel, From, To, ID, XMLNS, Type, SubEl) ->
|
|||||||
process_iq_admin(StateData, Channel, set, SubEl) ->
|
process_iq_admin(StateData, Channel, set, SubEl) ->
|
||||||
case xml:get_subtag(SubEl, "item") of
|
case xml:get_subtag(SubEl, "item") of
|
||||||
false ->
|
false ->
|
||||||
{error, "400", "Bad Request"};
|
{error, ?ERR_BAD_REQUEST};
|
||||||
ItemEl ->
|
ItemEl ->
|
||||||
Nick = xml:get_tag_attr_s("nick", ItemEl),
|
Nick = xml:get_tag_attr_s("nick", ItemEl),
|
||||||
Affiliation = xml:get_tag_attr_s("affiliation", ItemEl),
|
Affiliation = xml:get_tag_attr_s("affiliation", ItemEl),
|
||||||
@ -861,12 +859,12 @@ process_iq_admin(StateData, Channel, set, SubEl) ->
|
|||||||
process_admin(StateData, Channel, Nick, Affiliation, Role, Reason)
|
process_admin(StateData, Channel, Nick, Affiliation, Role, Reason)
|
||||||
end;
|
end;
|
||||||
process_iq_admin(StateData, Channel, get, SubEl) ->
|
process_iq_admin(StateData, Channel, get, SubEl) ->
|
||||||
{error, "501", "Not Implemented"}.
|
{error, ?ERR_FEATURE_NOT_IMPLEMENTED}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
process_admin(StateData, Channel, "", Affiliation, Role, Reason) ->
|
process_admin(StateData, Channel, "", Affiliation, Role, Reason) ->
|
||||||
{error, "501", "Not Implemented"};
|
{error, ?ERR_FEATURE_NOT_IMPLEMENTED};
|
||||||
|
|
||||||
process_admin(StateData, Channel, Nick, Affiliation, "none", Reason) ->
|
process_admin(StateData, Channel, Nick, Affiliation, "none", Reason) ->
|
||||||
case Reason of
|
case Reason of
|
||||||
@ -884,7 +882,7 @@ process_admin(StateData, Channel, Nick, Affiliation, "none", Reason) ->
|
|||||||
|
|
||||||
|
|
||||||
process_admin(StateData, Channel, Nick, Affiliation, Role, Reason) ->
|
process_admin(StateData, Channel, Nick, Affiliation, Role, Reason) ->
|
||||||
{error, "501", "Not Implemented"}.
|
{error, ?ERR_FEATURE_NOT_IMPLEMENTED}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
resend_offline_messages/1,
|
resend_offline_messages/1,
|
||||||
remove_user/1]).
|
remove_user/1]).
|
||||||
|
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(offline_msg, {user, timestamp, from, to, packet}).
|
-record(offline_msg, {user, timestamp, from, to, packet}).
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
process_local_iq/3]).
|
process_local_iq/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(private_storage, {userns, xml}).
|
-record(private_storage, {userns, xml}).
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
-export([start/1, init/0, process_iq/3]).
|
-export([start/1, init/0, process_iq/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
start(Opts) ->
|
start(Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
@ -97,12 +97,9 @@ process_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
case try_register(User, Password) of
|
case try_register(User, Password) of
|
||||||
ok ->
|
ok ->
|
||||||
{iq, ID, result, XMLNS, [SubEl]};
|
{iq, ID, result, XMLNS, [SubEl]};
|
||||||
{error, Code, Reason} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement,
|
[SubEl, Error]}
|
||||||
"error",
|
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Reason}]}]}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
@ -128,9 +125,9 @@ try_register(User, Password) ->
|
|||||||
{atomic, ok} ->
|
{atomic, ok} ->
|
||||||
ok;
|
ok;
|
||||||
{atomic, exists} ->
|
{atomic, exists} ->
|
||||||
{error, "400", "Bad Request"};
|
{error, ?ERR_BAD_REQUEST};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{error, "500", "Internal Server Error"}
|
{error, ?ERR_INTERNAL_SERVER_ERROR}
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
-include_lib("mnemosyne/include/mnemosyne.hrl").
|
-include_lib("mnemosyne/include/mnemosyne.hrl").
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(roster, {uj,
|
-record(roster, {uj,
|
||||||
user,
|
user,
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
stop/0,
|
stop/0,
|
||||||
process_local_iq/3]).
|
process_local_iq/3]).
|
||||||
|
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
start(Opts) ->
|
start(Opts) ->
|
||||||
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
|
||||||
@ -43,11 +43,9 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
|||||||
{result, Res} ->
|
{result, Res} ->
|
||||||
{iq, ID, result, XMLNS,
|
{iq, ID, result, XMLNS,
|
||||||
[{xmlelement, "query", [{"xmlns", XMLNS}], Res}]};
|
[{xmlelement, "query", [{"xmlns", XMLNS}], Res}]};
|
||||||
{error, Code, Desc} ->
|
{error, Error} ->
|
||||||
{iq, ID, error, XMLNS,
|
{iq, ID, error, XMLNS,
|
||||||
[SubEl, {xmlelement, "error",
|
[SubEl, Error]}
|
||||||
[{"code", Code}],
|
|
||||||
[{xmlcdata, Desc}]}]}
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -98,7 +96,7 @@ get_local_stats(["running nodes", ENode], Names) ->
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
get_local_stats(_, _) ->
|
get_local_stats(_, _) ->
|
||||||
{error, "501", "Not Implemented"}.
|
{error, ?ERR_FEATURE_NOT_IMPLEMENTED}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
process_local_iq/3]).
|
process_local_iq/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
|
|
||||||
start(Opts) ->
|
start(Opts) ->
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
remove_user/1]).
|
remove_user/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
|
|
||||||
-record(vcard_search, {user, luser,
|
-record(vcard_search, {user, luser,
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
process_local_iq/3]).
|
process_local_iq/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("namespaces.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user