24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-12 21:52:07 +02:00

Convert to exmpp. Note that this module hasn't been tested yet!

SVN Revision: 1434
This commit is contained in:
Jean-Sébastien Pédron 2008-07-11 12:41:48 +00:00
parent 8bfccb42a9
commit 5610d00b4d
2 changed files with 66 additions and 67 deletions

View File

@ -4,6 +4,9 @@
src/ejabberd_c2s.erl: Exmpp now takes care of stanza serialization and
compatible namespaces.
* src/ejabberd_service.erl: Convert to exmpp. Note that this module
hasn't been tested yet!
2008-07-09 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/ejabberd_c2s.erl: Convert #xmlelement returned by the

View File

@ -47,8 +47,9 @@
handle_info/3,
terminate/3]).
-include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl").
-include("jlib.hrl").
-record(state, {socket, sockmod, streamid,
hosts, password, access,
@ -62,31 +63,10 @@
-define(FSMOPTS, []).
-endif.
-define(STREAM_HEADER,
"<?xml version='1.0'?>"
"<stream:stream "
"xmlns:stream='http://etherx.jabber.org/streams' "
"xmlns='jabber:component:accept' "
"id='~s' from='~s'>"
).
-define(STREAM_TRAILER, "</stream:stream>").
-define(INVALID_HEADER_ERR,
"<stream:stream>"
"<stream:error>Invalid Stream Header</stream:error>"
"</stream:stream>"
).
-define(INVALID_HANDSHAKE_ERR,
"<stream:error>Invalid Handshake</stream:error>"
"</stream:stream>"
).
-define(INVALID_XML_ERR,
xml:element_to_string(?SERR_XML_NOT_WELL_FORMED)).
-define(INVALID_NS_ERR,
xml:element_to_string(?SERR_INVALID_NAMESPACE)).
% These are the namespace already declared by the stream opening. This is
% used at serialization time.
-define(DEFAULT_NS, ?NS_COMPONENT_ACCEPT).
-define(PREFIXED_NS, [{?NS_XMPP, ?NS_XMPP_pfx}]).
%%%----------------------------------------------------------------------
%%% API
@ -167,24 +147,32 @@ init([{SockMod, Socket}, Opts]) ->
%% {stop, Reason, NewStateData}
%%----------------------------------------------------------------------
wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
wait_for_stream({xmlstreamstart, #xmlel{ns = NS}}, StateData) ->
% TODO
case xml:get_attr_s("xmlns", Attrs) of
"jabber:component:accept" ->
Header = io_lib:format(?STREAM_HEADER,
[StateData#state.streamid, ?MYNAME]),
send_text(StateData, Header),
case NS of
?NS_COMPONENT_ACCEPT ->
Opening_Reply = exmpp_stream:opening_reply(?MYNAME,
?NS_COMPONENT_ACCEPT,
{0, 0}, StateData#state.streamid),
send_element(StateData, Opening_Reply),
{next_state, wait_for_handshake, StateData};
_ ->
send_text(StateData, ?INVALID_HEADER_ERR),
Error = #xmlel{ns = ?NS_XMPP, name = 'stream', children = [
#xmlel{ns = ?NS_XMPP, name = 'error', children = [
#xmlcdata{cdata = <<"Invalid Stream Header">>}
]}
]},
send_element(StateData, Error),
{stop, normal, StateData}
end;
wait_for_stream({xmlstreamerror, _}, StateData) ->
Header = io_lib:format(?STREAM_HEADER,
["none", ?MYNAME]),
send_text(StateData,
Header ++ ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
Opening_Reply = exmpp_stream:opening_reply(?MYNAME,
?NS_COMPONENT_ACCEPT,
{0, 0}, "none"),
send_element(StateData, Opening_Reply),
send_element(StateData, exmpp_stream:error('xml-not-well-formed')),
send_element(StateData, exmpp_stream:closing()),
{stop, normal, StateData};
wait_for_stream(closed, StateData) ->
@ -192,13 +180,13 @@ wait_for_stream(closed, StateData) ->
wait_for_handshake({xmlstreamelement, El}, StateData) ->
{xmlelement, Name, _Attrs, Els} = El,
case {Name, xml:get_cdata(Els)} of
{"handshake", Digest} ->
case {El#xmlel.name, exmpp_xml:get_cdata(El)} of
{'handshake', Digest} ->
case sha:sha(StateData#state.streamid ++
StateData#state.password) of
Digest ->
send_text(StateData, "<handshake/>"),
send_element(StateData,
#xmlel{ns = ?NS_COMPONENT_ACCEPT, name = 'handshake'}),
lists:foreach(
fun(H) ->
ejabberd_router:register_route(H),
@ -206,7 +194,10 @@ wait_for_handshake({xmlstreamelement, El}, StateData) ->
end, StateData#state.hosts),
{next_state, stream_established, StateData};
_ ->
send_text(StateData, ?INVALID_HANDSHAKE_ERR),
send_element(StateData,
#xmlel{ns = ?NS_XMPP, name = 'error', children = [
#xmlcdata{cdata = <<"Invalid Handshake">>}]}),
send_element(StateData, exmpp_stream:closing()),
{stop, normal, StateData}
end;
_ ->
@ -217,7 +208,8 @@ wait_for_handshake({xmlstreamend, _Name}, StateData) ->
{stop, normal, StateData};
wait_for_handshake({xmlstreamerror, _}, StateData) ->
send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
send_element(StateData, exmpp_stream:error('xml-not-well-formed')),
send_element(StateData, exmpp_stream:closing()),
{stop, normal, StateData};
wait_for_handshake(closed, StateData) ->
@ -225,20 +217,18 @@ wait_for_handshake(closed, StateData) ->
stream_established({xmlstreamelement, El}, StateData) ->
NewEl = jlib:remove_attr("xmlns", El),
{xmlelement, Name, Attrs, _Els} = NewEl,
From = xml:get_attr_s("from", Attrs),
From = exmpp_stanza:get_sender(El),
FromJID = case StateData#state.check_from of
%% If the admin does not want to check the from field
%% when accept packets from any address.
%% In this case, the component can send packet of
%% behalf of the server users.
false -> jlib:string_to_jid(From);
false -> exmpp_jid:string_to_jid(From);
%% The default is the standard behaviour in XEP-0114
_ ->
FromJID1 = jlib:string_to_jid(From),
FromJID1 = exmpp_jib:string_to_jid(From),
case FromJID1 of
#jid{lserver = Server} ->
#jid{ldomain = Server} ->
case lists:member(Server, StateData#state.hosts) of
true -> FromJID1;
false -> error
@ -246,18 +236,18 @@ stream_established({xmlstreamelement, El}, StateData) ->
_ -> error
end
end,
To = xml:get_attr_s("to", Attrs),
To = exmpp_stanza:get_recipient(El),
ToJID = case To of
"" -> error;
_ -> jlib:string_to_jid(To)
undefined -> error;
_ -> exmpp_jib:string_to_jid(To)
end,
if ((Name == "iq") or
(Name == "message") or
(Name == "presence")) and
if ((El#xmlel.name == 'iq') or
(El#xmlel.name == 'message') or
(El#xmlel.name == 'presence')) and
(ToJID /= error) and (FromJID /= error) ->
ejabberd_router:route(FromJID, ToJID, NewEl);
ejabberd_router:route(FromJID, ToJID, El);
true ->
Err = jlib:make_error_reply(NewEl, ?ERR_BAD_REQUEST),
Err = exmpp_stanza:reply_with_error(El, 'bad-request'),
send_element(StateData, Err),
error
end,
@ -268,7 +258,8 @@ stream_established({xmlstreamend, _Name}, StateData) ->
{stop, normal, StateData};
stream_established({xmlstreamerror, _}, StateData) ->
send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
send_element(StateData, exmpp_stream:error('xml-not-well-formed')),
send_element(StateData, exmpp_stream:closing()),
{stop, normal, StateData};
stream_established(closed, StateData) ->
@ -322,22 +313,25 @@ code_change(_OldVsn, StateName, StateData, _Extra) ->
%% {stop, Reason, NewStateData}
%%----------------------------------------------------------------------
handle_info({send_text, Text}, StateName, StateData) ->
% XXX OLD FORMAT: This clause should be removed.
send_text(StateData, Text),
{next_state, StateName, StateData};
handle_info({send_element, El}, StateName, StateData) ->
send_element(StateData, El),
{next_state, StateName, StateData};
handle_info({route, From, To, Packet}, StateName, StateData) ->
handle_info({route, FromOld, ToOld, PacketOld}, StateName, StateData) ->
%% XXX OLD FORMAT: From, To and Packet are in the old format.
Packet = exmpp_xml:xmlelement_to_xmlel(PacketOld,
[?NS_JABBER_CLIENT], ?PREFIXED_NS),
From = jlib:from_old_jid(FromOld),
To = jlib:from_old_jid(ToOld),
case acl:match_rule(global, StateData#state.access, From) of
allow ->
{xmlelement, Name, Attrs, Els} = Packet,
Attrs2 = jlib:replace_from_to_attrs(jlib:jid_to_string(From),
jlib:jid_to_string(To),
Attrs),
Text = xml:element_to_string({xmlelement, Name, Attrs2, Els}),
send_text(StateData, Text);
El1 = exmpp_stanza:set_sender(Packet, From),
El2 = exmpp_stanza:set_recipient(El1, To),
send_element(StateData, El2);
deny ->
Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
Err = exmpp_stanza:reply_with_error(Packet, 'not-allowed'),
ejabberd_router:route(To, From, Err)
end,
{next_state, StateName, StateData}.
@ -369,8 +363,10 @@ terminate(Reason, StateName, StateData) ->
send_text(StateData, Text) ->
(StateData#state.sockmod):send(StateData#state.socket, Text).
send_element(StateData, #xmlel{ns = ?NS_XMPP, name = 'stream'} = El) ->
send_text(StateData, exmpp_stream:to_list(El));
send_element(StateData, El) ->
send_text(StateData, xml:element_to_string(El)).
send_text(StateData, exmpp_stanza:to_list(El)).
new_id() ->
randoms:get_string().