mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Convert to exmpp. Note that this module hasn't been tested yet!
SVN Revision: 1434
This commit is contained in:
parent
8bfccb42a9
commit
5610d00b4d
@ -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
|
||||
|
@ -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().
|
||||
|
Loading…
Reference in New Issue
Block a user