+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>
* src/ejabberd_c2s.erl: More correct stream closing
--- /dev/null
+%%%----------------------------------------------------------------------
+%%% 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.
+
+
+
--- /dev/null
+%%%----------------------------------------------------------------------
+%%% 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]).
+
+
+
+
gen_mod:start(),
ejabberd_config:start(),
ejabberd_auth:start(),
+ cyrsasl:start(),
Sup = ejabberd_sup:start_link(),
start(),
load_modules(),
check_password(User, Password) ->
LUser = jlib:tolower(User),
- F = fun() ->
- case mnesia:read({passwd, LUser}) of
- [E] ->
- E#passwd.password
- end
- end,
- case mnesia:transaction(F) of
- {atomic, Password} ->
+ case catch mnesia:dirty_read({passwd, LUser}) of
+ [#passwd{password = Password}] ->
true;
_ ->
false
-export([start/2, receiver/4, send_text/2, send_element/2]).
%% 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_sync_event/4,
code_change/4,
terminate/3]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
-define(SETS, gb_sets).
-record(state, {socket, receiver, streamid,
+ sasl_state,
access,
shaper,
user = "", server = ?MYNAME, resource = "",
"<?xml version='1.0'?>"
"<stream:stream xmlns='jabber:client' "
"xmlns:stream='http://etherx.jabber.org/streams' "
- "id='~s' from='~s'>"
+ "id='~s' from='~s'~s>"
).
-define(STREAM_TRAILER, "</stream:stream>").
-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,
- "<stream:error code='400'>Invalid XML</stream:error>").
+ xml:element_to_string(?SERR_XML_NOT_WELL_FORMED)).
%%%----------------------------------------------------------------------
%%% API
%%----------------------------------------------------------------------
wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
- % TODO
- Header = io_lib:format(?STREAM_HEADER,
- [StateData#state.streamid, ?MYNAME]),
- send_text(StateData#state.socket, Header),
- case lists:keysearch("xmlns:stream", 1, Attrs) of
- {value, {"xmlns:stream", "http://etherx.jabber.org/streams"}} ->
- % TODO
- {next_state, wait_for_auth, StateData};
+ case xml:get_attr_s("xmlns:stream", Attrs) of
+ ?NS_STREAM ->
+ case xml:get_attr_s("version", Attrs) of
+ "1.0" ->
+ Header = io_lib:format(?STREAM_HEADER,
+ [StateData#state.streamid,
+ ?MYNAME,
+ " 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}
end;
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};
wait_for_stream(closed, StateData) ->
wait_for_auth({xmlstreamelement, El}, StateData) ->
case is_auth_packet(El) of
- {auth, ID, {U, P, D, ""}} ->
+ {auth, ID, get, {"", _, _, _}} ->
+ Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
+ send_element(StateData#state.socket, Err),
+ {next_state, wait_for_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, 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, {U, P, D, R}} ->
+ {auth, ID, set, {U, P, D, R}} ->
io:format("AUTH: ~p~n", [{U, P, D, R}]),
JID = {U, ?MYNAME, R},
case acl:match_rule(StateData#state.access, JID) of
pres_t = ?SETS:from_list(Ts)}};
_ ->
Err = jlib:make_error_reply(
- El, "401", "Unauthorized"),
+ El, ?ERR_FORBIDDEN),
send_element(StateData#state.socket, Err),
{next_state, wait_for_auth, StateData}
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),
{next_state, wait_for_auth, StateData}
end;
{stop, normal, 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};
wait_for_auth(closed, 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) ->
{xmlelement, Name, Attrs, Els} = El,
Server = StateData#state.server,
{stop, normal, 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};
session_established(closed, StateData) ->
case jlib:iq_query_info(El) of
{iq, ID, Type, ?NS_AUTH, SubEl} ->
{xmlelement, _, _, Els} = SubEl,
- {auth, ID,
+ {auth, ID, Type,
get_auth_tags(Els, "", "", "", "")};
_ ->
false
]).
-include("ejabberd.hrl").
+-include("jlib.hrl").
-record(state, {mydomain, iqtable}).
ok
end;
{"", _, _} ->
- Err = jlib:make_error_reply(Packet, "404", "Not Found"),
+ Err = jlib:make_error_reply(Packet, ?ERR_JID_NOT_FOUND),
ejabberd_router ! {route,
{"", State#state.mydomain, ""}, From, Err},
ok;
Err}
end;
_ ->
- % TODO
ok
end;
reply ->
ok;
_ ->
- Err = jlib:make_error_reply(Packet, "400", "Bad Request"),
+ Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST),
ejabberd_router ! {route,
{"", State#state.mydomain, ""}, From, Err},
ok
terminate/3]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
-record(state, {socket, pid,
user = "", server = ?MYNAME, resource = ""
-export([make_result_iq_reply/1,
make_error_reply/3,
+ make_error_reply/2,
make_error_element/2,
make_correct_from_to_attrs/3,
replace_from_to_attrs/3,
iq_to_xml/1,
parse_xdata_submit/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) ->
% ok.
[{"code", Code}],
[{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) ->
To = xml:get_attr("to", Attrs),
From = xml:get_attr("from", Attrs),
[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}).
process_sm_iq/3]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
start(Opts) ->
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
case acl:match_rule(configure, From) of
deny ->
- {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
- [{"code", "405"}],
- [{xmlcdata, "Not Allowed"}]}]};
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
allow ->
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
case Type of
[{"xmlns", XMLNS}],
Res
}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end
end;
_ ->
[{xmlelement, "query", [{"xmlns", XMLNS}],
Res
}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end
end
end.
Node ->
case rpc:call(Node, mnesia, system_info, [tables]) of
{badrpc, Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
Tables ->
STables = lists:sort(Tables),
{result, [{xmlelement, "title", [],
Node ->
case rpc:call(Node, gen_mod, loaded_modules, []) of
{badrpc, Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
Modules ->
SModules = lists:sort(Modules),
{result, [{xmlelement, "title", [],
};
get_form(_, Lang) ->
- {error, "503", "Service Unavailable"}.
+ {error, ?ERR_SERVICE_UNAVAILABLE}.
{value, {_, [String]}} ->
case rpc:call(Node, mnesia, backup, [String]) of
{badrpc, Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
{error, Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
_ ->
{result, []}
end;
case rpc:call(Node, mnesia, restore,
[String, [{default_op, keep_tables}]]) of
{badrpc, Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
{error, Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
_ ->
{result, []}
end;
{value, {_, [String]}} ->
case rpc:call(Node, mnesia, dump_to_textfile, [String]) of
{badrpc, Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
{error, Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
_ ->
{result, []}
end;
{result, []};
set_form(_, Lang, XData) ->
- {error, "503", "Service Unavailable"}.
+ {error, ?ERR_SERVICE_UNAVAILABLE}.
[{"xmlns", XMLNS}],
Res
}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end
end;
_ ->
[{xmlelement, "query", [{"xmlns", XMLNS}],
Res
}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end
end
end.
]};
get_sm_form(_, _, Lang) ->
- {error, "503", "Service Unavailable"}.
+ {error, ?ERR_SERVICE_UNAVAILABLE}.
set_sm_form(_, _, Lang, XData) ->
- {error, "503", "Service Unavailable"}.
+ {error, ?ERR_SERVICE_UNAVAILABLE}.
unregister_feature/1]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
-define(EMPTY_INFO_RESULT,
{iq, ID, result, XMLNS, [{xmlelement, "query",
Lang = xml:get_tag_attr_s("xml:lang", SubEl),
case Type of
set ->
- {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
- [{"code", "405"}],
- [{xmlcdata, "Not Allowed"}]}]};
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
get ->
Node = string:tokens(xml:get_tag_attr_s("node", SubEl), "/"),
[{xmlelement, "query", [{"xmlns", ?NS_DISCO_ITEMS}],
Res
}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end
end.
process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
case Type of
set ->
- {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
- [{"code", "405"}],
- [{xmlcdata, "Not Allowed"}]}]};
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
get ->
case string:tokens(xml:get_tag_attr_s("node", SubEl), "/") of
[] ->
[feature_to_xml({?NS_IQDATA})]}]};
_ ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", "501"}],
- [{xmlcdata, "Not Implemented"}]}]}
+ [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}
end
end.
get_local_items(["all users", [$@ | Diap]], Server, Lang) ->
case catch ejabberd_auth:dirty_get_registered_users() of
{'EXIT', Reason} ->
- {error, "500", "Internal Server Error"};
+ ?ERR_INTERNAL_SERVER_ERROR;
Users ->
SUsers = lists:sort(Users),
case catch begin
end, Sub)
end of
{'EXIT', Reason} ->
- {error, "406", "Not Acceptable"};
+ % TODO: must be "not acceptable"
+ ?ERR_BAD_REQUEST;
Res ->
{result, Res}
end
{result, []};
get_local_items(_, _, _) ->
- {error, "501", "Not Implemented"}.
+ {error, ?ERR_FEATURE_NOT_IMPLEMENTED}.
{User, _, _} = To,
case Type of
set ->
- {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
- [{"code", "405"}],
- [{xmlcdata, "Not Allowed"}]}]};
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
get ->
case xml:get_tag_attr_s("node", SubEl) of
"" ->
}]};
_ ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", "501"}],
- [{xmlcdata, "Not Implemented"}]}]}
+ [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}
end
end.
process_sm_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
case Type of
set ->
- {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
- [{"code", "405"}],
- [{xmlcdata, "Not Allowed"}]}]};
+ {iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};
get ->
case xml:get_tag_attr_s("node", SubEl) of
"" ->
[feature_to_xml({?NS_IQDATA})]}]};
_ ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", "501"}],
- [{xmlcdata, "Not Implemented"}]}]}
+ [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}
end
end.
-export([start/1, init/1, stop/0]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
get_user_and_encoding/2]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
-define(DEFAULT_IRC_ENCODING, "koi8-r").
[{"xmlns", XMLNS}],
Res
}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end
end;
_ ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", "405"}],
- [{xmlcdata, "Not Allowed"}]}]}
+ [SubEl, ?ERR_NOT_ALLOWED]}
end;
get ->
Node =
[{xmlelement, "query", [{"xmlns", XMLNS}],
Res
}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end
end.
Customs =
case catch mnesia:dirty_read({irc_custom, {LUser, LServer}}) of
{'EXIT', Reason} ->
- {error, "500", "Internal Server Error"};
+ {error, ?ERR_INTERNAL_SERVER_ERROR};
[] ->
{User, []};
[#irc_custom{data = Data}] ->
get_form(_, _, Lang) ->
- {error, "503", "Service Unavailable"}.
+ {error, ?ERR_SERVICE_UNAVAILABLE}.
set_form(_, _, Lang, XData) ->
- {error, "503", "Service Unavailable"}.
+ {error, ?ERR_SERVICE_UNAVAILABLE}.
get_user_and_encoding(From, IRCServer) ->
code_change/4]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
-define(SETS, gb_sets).
ID, XMLNS, Type, SubEl);
_ ->
Err = jlib:make_error_reply(
- El, "503", "Service Unavailable"),
+ El, ?ERR_SERVICE_UNAVAILABLE),
ejabberd_router:route(To, From, Err)
end,
{next_state, StateName, StateData};
[{"xmlns", XMLNS}],
ResEls
}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end,
ejabberd_router:route(To, From,
jlib:iq_to_xml(ResIQ));
process_iq_admin(StateData, Channel, set, SubEl) ->
case xml:get_subtag(SubEl, "item") of
false ->
- {error, "400", "Bad Request"};
+ {error, ?ERR_BAD_REQUEST};
ItemEl ->
Nick = xml:get_tag_attr_s("nick", ItemEl),
Affiliation = xml:get_tag_attr_s("affiliation", ItemEl),
process_admin(StateData, Channel, Nick, Affiliation, Role, Reason)
end;
process_iq_admin(StateData, Channel, get, SubEl) ->
- {error, "501", "Not Implemented"}.
+ {error, ?ERR_FEATURE_NOT_IMPLEMENTED}.
process_admin(StateData, Channel, "", Affiliation, Role, Reason) ->
- {error, "501", "Not Implemented"};
+ {error, ?ERR_FEATURE_NOT_IMPLEMENTED};
process_admin(StateData, Channel, Nick, Affiliation, "none", Reason) ->
case Reason of
process_admin(StateData, Channel, Nick, Affiliation, Role, Reason) ->
- {error, "501", "Not Implemented"}.
+ {error, ?ERR_FEATURE_NOT_IMPLEMENTED}.
resend_offline_messages/1,
remove_user/1]).
--include("namespaces.hrl").
+-include("jlib.hrl").
-record(offline_msg, {user, timestamp, from, to, packet}).
process_local_iq/3]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
-record(private_storage, {userns, xml}).
-export([start/1, init/0, process_iq/3]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
start(Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
case try_register(User, Password) of
ok ->
{iq, ID, result, XMLNS, [SubEl]};
- {error, Code, Reason} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement,
- "error",
- [{"code", Code}],
- [{xmlcdata, Reason}]}]}
+ [SubEl, Error]}
end
end
end;
{atomic, ok} ->
ok;
{atomic, exists} ->
- {error, "400", "Bad Request"};
+ {error, ?ERR_BAD_REQUEST};
{error, Reason} ->
- {error, "500", "Internal Server Error"}
+ {error, ?ERR_INTERNAL_SERVER_ERROR}
end
end.
-include_lib("mnemosyne/include/mnemosyne.hrl").
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
-record(roster, {uj,
user,
stop/0,
process_local_iq/3]).
--include("namespaces.hrl").
+-include("jlib.hrl").
start(Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
{result, Res} ->
{iq, ID, result, XMLNS,
[{xmlelement, "query", [{"xmlns", XMLNS}], Res}]};
- {error, Code, Desc} ->
+ {error, Error} ->
{iq, ID, error, XMLNS,
- [SubEl, {xmlelement, "error",
- [{"code", Code}],
- [{xmlcdata, Desc}]}]}
+ [SubEl, Error]}
end
end.
end;
get_local_stats(_, _) ->
- {error, "501", "Not Implemented"}.
+ {error, ?ERR_FEATURE_NOT_IMPLEMENTED}.
process_local_iq/3]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
start(Opts) ->
remove_user/1]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").
-record(vcard_search, {user, luser,
process_local_iq/3]).
-include("ejabberd.hrl").
--include("namespaces.hrl").
+-include("jlib.hrl").