25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

Convert to exmpp.

PR:		EJABP-1

SVN Revision: 1663
This commit is contained in:
Jean-Sébastien Pédron 2008-10-20 10:34:00 +00:00
parent 50b1e4c36f
commit 0313adaec6
3 changed files with 315 additions and 362 deletions

View File

@ -1,3 +1,8 @@
2008-10-20 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/mod_irc/mod_irc.erl, src/mod_irc/mod_irc_connection.erl: Convert
to exmpp.
2008-10-13 Jean-Sébastien Pédron <js.pedron@meetic-corp.com> 2008-10-13 Jean-Sébastien Pédron <js.pedron@meetic-corp.com>
* src/web/ejabberd_http.erl, src/web/ejabberd_http_poll.erl, * src/web/ejabberd_http.erl, src/web/ejabberd_http_poll.erl,

View File

@ -40,8 +40,9 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]). terminate/2, code_change/3]).
-include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("jlib.hrl").
-record(irc_connection, {jid_server_host, pid}). -record(irc_connection, {jid_server_host, pid}).
-record(irc_custom, {us_host, data}). -record(irc_custom, {us_host, data}).
@ -193,60 +194,55 @@ do_route(Host, ServerHost, Access, From, To, Packet, DefEnc) ->
allow -> allow ->
do_route1(Host, ServerHost, From, To, Packet, DefEnc); do_route1(Host, ServerHost, From, To, Packet, DefEnc);
_ -> _ ->
{xmlelement, _Name, Attrs, _Els} = Packet, Lang = exmpp_stanza:get_lang(Packet),
Lang = xml:get_attr_s("xml:lang", Attrs), ErrText = translate:translate(Lang,
ErrText = "Access denied by service policy", "Access denied by service policy"),
Err = jlib:make_error_reply(Packet, Err = exmpp_stanza:reply_with_error(Packet,
?ERRT_FORBIDDEN(Lang, ErrText)), exmpp_stanza:error(Packet#xmlel.ns,
'forbidden', {Lang, ErrText})),
ejabberd_router:route(To, From, Err) ejabberd_router:route(To, From, Err)
end. end.
do_route1(Host, ServerHost, From, To, Packet, DefEnc) -> do_route1(Host, ServerHost, From, To, Packet, DefEnc) ->
#jid{user = ChanServ, resource = Resource} = To, #jid{node = ChanServ, resource = Resource} = To,
{xmlelement, _Name, _Attrs, _Els} = Packet,
case ChanServ of case ChanServ of
"" -> undefined ->
case Resource of case Resource of
"" -> undefined ->
case jlib:iq_query_info(Packet) of case exmpp_iq:xmlel_to_iq(Packet) of
#iq{type = get, xmlns = ?NS_DISCO_INFO = XMLNS, #iq{type = get, ns = ?NS_DISCO_INFO = XMLNS,
sub_el = _SubEl, lang = Lang} = IQ -> lang = Lang} = IQ_Rec ->
Res = IQ#iq{type = result, Result = #xmlel{ns = XMLNS, name = 'query',
sub_el = [{xmlelement, "query", children = iq_disco(Lang)},
[{"xmlns", XMLNS}], Res = exmpp_iq:result(IQ_Rec, Result),
iq_disco(Lang)}]},
ejabberd_router:route(To, ejabberd_router:route(To,
From, From,
jlib:iq_to_xml(Res)); exmpp_iq:iq_to_xmlel(Res));
#iq{type = get, xmlns = ?NS_DISCO_ITEMS = XMLNS} = IQ -> #iq{type = get, ns = ?NS_DISCO_ITEMS = XMLNS} = IQ_Rec ->
Res = IQ#iq{type = result, Result = #xmlel{ns = XMLNS, name = 'query'},
sub_el = [{xmlelement, "query", Res = exmpp_iq:result(IQ_Rec, Result),
[{"xmlns", XMLNS}],
[]}]},
ejabberd_router:route(To, ejabberd_router:route(To,
From, From,
jlib:iq_to_xml(Res)); exmpp_iq:iq_to_xmlel(Res));
#iq{xmlns = ?NS_REGISTER} = IQ -> #iq{kind = request, ns = ?NS_INBAND_REGISTER} = IQ_Rec ->
process_register(Host, From, To, DefEnc, IQ); process_register(Host, From, To, DefEnc, IQ_Rec);
#iq{type = get, xmlns = ?NS_VCARD = XMLNS, #iq{type = get, ns = ?NS_VCARD = XMLNS,
lang = Lang} = IQ -> lang = Lang} = IQ_Rec ->
Res = IQ#iq{type = result, Result = #xmlel{ns = XMLNS, name = 'vCard',
sub_el = children = iq_get_vcard(Lang)},
[{xmlelement, "vCard", Res = exmpp_iq:result(IQ_Rec, Result),
[{"xmlns", XMLNS}],
iq_get_vcard(Lang)}]},
ejabberd_router:route(To, ejabberd_router:route(To,
From, From,
jlib:iq_to_xml(Res)); exmpp_iq:iq_to_xmlel(Res));
#iq{} = _IQ -> #iq{} = _IQ_Rec ->
Err = jlib:make_error_reply( Err = exmpp_iq:error(
Packet, ?ERR_FEATURE_NOT_IMPLEMENTED), Packet, 'feature-not-implemented'),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
_ -> _ ->
ok ok
end; end;
_ -> _ ->
Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), Err = exmpp_stanza:reply_with_error(Packet, 'bad-request'),
ejabberd_router:route(To, From, Err) ejabberd_router:route(To, From, Err)
end; end;
_ -> _ ->
@ -280,8 +276,8 @@ do_route1(Host, ServerHost, From, To, Packet, DefEnc) ->
[[_ | _] = Nick, [_ | _] = Server] -> [[_ | _] = Nick, [_ | _] = Server] ->
case ets:lookup(irc_connection, {From, Server, Host}) of case ets:lookup(irc_connection, {From, Server, Host}) of
[] -> [] ->
Err = jlib:make_error_reply( Err = exmpp_stanza:reply_with_error(
Packet, ?ERR_SERVICE_UNAVAILABLE), Packet, 'service-unavailable'),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
[R] -> [R] ->
Pid = R#irc_connection.pid, Pid = R#irc_connection.pid,
@ -292,8 +288,8 @@ do_route1(Host, ServerHost, From, To, Packet, DefEnc) ->
ok ok
end; end;
_ -> _ ->
Err = jlib:make_error_reply( Err = exmpp_stanza:reply_with_error(
Packet, ?ERR_BAD_REQUEST), Packet, 'bad-request'),
ejabberd_router:route(To, From, Err) ejabberd_router:route(To, From, Err)
end end
end end
@ -305,164 +301,148 @@ closed_connection(Host, From, Server) ->
iq_disco(Lang) -> iq_disco(Lang) ->
[{xmlelement, "identity", [#xmlel{ns = ?NS_DISCO_INFO, name = 'identity', attrs =
[{"category", "conference"}, [#xmlattr{name = 'category', value = "conference"},
{"type", "irc"}, #xmlattr{name = 'type', value = "irc"},
{"name", translate:translate(Lang, "IRC Transport")}], []}, #xmlattr{name = 'name', value = translate:translate(Lang, "IRC Transport")}]},
{xmlelement, "feature", #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs =
[{"var", ?NS_MUC}], []}, [#xmlattr{name = 'var', value = ?NS_MUC_s}]},
{xmlelement, "feature", #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs =
[{"var", ?NS_REGISTER}], []}, [#xmlattr{name = 'var', value = ?NS_INBAND_REGISTER_s}]},
{xmlelement, "feature", #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs =
[{"var", ?NS_VCARD}], []}]. [#xmlattr{name = 'var', value = ?NS_VCARD_s}]}].
iq_get_vcard(Lang) -> iq_get_vcard(Lang) ->
[{xmlelement, "FN", [], [#xmlel{ns = ?NS_VCARD, name = 'FN', children =
[{xmlcdata, "ejabberd/mod_irc"}]}, [#xmlcdata{cdata = <<"ejabberd/mod_irc">>}]},
{xmlelement, "URL", [], #xmlel{ns = ?NS_VCARD, name = 'URL', children =
[{xmlcdata, ?EJABBERD_URI}]}, [#xmlcdata{cdata = list_to_binary(?EJABBERD_URI)}]},
{xmlelement, "DESC", [], #xmlel{ns = ?NS_VCARD, name = 'DESC', children =
[{xmlcdata, translate:translate(Lang, "ejabberd IRC module") ++ [#xmlcdata{cdata = list_to_binary(translate:translate(Lang, "ejabberd IRC module") ++
"\nCopyright (c) 2003-2008 Alexey Shchepin"}]}]. "\nCopyright (c) 2003-2008 Alexey Shchepin")}]}].
process_register(Host, From, To, DefEnc, #iq{} = IQ) -> process_register(Host, From, To, DefEnc, #iq{} = IQ_Rec) ->
case catch process_irc_register(Host, From, To, DefEnc, IQ) of case catch process_irc_register(Host, From, To, DefEnc, IQ_Rec) of
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]); ?ERROR_MSG("~p", [Reason]);
ResIQ -> ResIQ ->
if if
ResIQ /= ignore -> ResIQ /= ignore ->
ejabberd_router:route(To, From, ejabberd_router:route(To, From,
jlib:iq_to_xml(ResIQ)); exmpp_iq:iq_to_xmlel(ResIQ));
true -> true ->
ok ok
end end
end. end.
find_xdata_el({xmlelement, _Name, _Attrs, SubEls}) -> find_xdata_el(#xmlel{children = SubEls}) ->
find_xdata_el1(SubEls). find_xdata_el1(SubEls).
find_xdata_el1([]) -> find_xdata_el1([]) ->
false; false;
find_xdata_el1([{xmlelement, Name, Attrs, SubEls} | Els]) -> find_xdata_el1([#xmlel{ns = ?NS_DATA_FORMS} = El | _Els]) ->
case xml:get_attr_s("xmlns", Attrs) of El;
?NS_XDATA ->
{xmlelement, Name, Attrs, SubEls};
_ ->
find_xdata_el1(Els)
end;
find_xdata_el1([_ | Els]) -> find_xdata_el1([_ | Els]) ->
find_xdata_el1(Els). find_xdata_el1(Els).
process_irc_register(Host, From, _To, DefEnc, process_irc_register(Host, From, _To, DefEnc,
#iq{type = Type, xmlns = XMLNS, #iq{type = get, ns = XMLNS,
lang = Lang, sub_el = SubEl} = IQ) -> lang = Lang, payload = SubEl} = IQ_Rec) ->
case Type of Node =
set -> string:tokens(exmpp_xml:get_attribute(SubEl, 'node', ""), "/"),
case get_form(Host, From, Node, Lang ,DefEnc) of
{result, Res} ->
Result = #xmlel{ns = XMLNS, name = 'query', children = Res},
exmpp_iq:result(IQ_Rec, Result);
{error, Error} ->
exmpp_iq:error(IQ_Rec, Error)
end;
process_irc_register(Host, From, _To, _DefEnc,
#iq{type = set, ns = XMLNS,
lang = Lang, payload = SubEl} = IQ_Rec) ->
XDataEl = find_xdata_el(SubEl), XDataEl = find_xdata_el(SubEl),
case XDataEl of case XDataEl of
false -> false ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ACCEPTABLE]}; exmpp_iq:error(IQ_Rec, 'not-acceptable');
{xmlelement, _Name, Attrs, _SubEls} -> _ ->
case xml:get_attr_s("type", Attrs) of case exmpp_stanza:get_type(XDataEl) of
"cancel" -> "cancel" ->
IQ#iq{type = result, Result = #xmlel{ns = XMLNS, name = 'query'},
sub_el = [{xmlelement, "query", exmpp_iq:result(IQ_Rec, Result);
[{"xmlns", XMLNS}], []}]};
"submit" -> "submit" ->
XData = jlib:parse_xdata_submit(XDataEl), XData = jlib:parse_xdata_submit(XDataEl),
case XData of case XData of
invalid -> invalid ->
IQ#iq{type = error, exmpp_iq:error(IQ_Rec, 'bad-request');
sub_el = [SubEl, ?ERR_BAD_REQUEST]};
_ -> _ ->
Node = string:tokens( Node = string:tokens(
xml:get_tag_attr_s("node", SubEl), exmpp_xml:get_attribute(SubEl, "node", ""),
"/"), "/"),
case set_form( case set_form(
Host, From, Node, Lang, XData) of Host, From, Node, Lang, XData) of
{result, Res} -> {result, Res} ->
IQ#iq{type = result, Result = #xmlel{ns = XMLNS, name = 'query',
sub_el = [{xmlelement, "query", children = Res},
[{"xmlns", XMLNS}], exmpp_iq:result(IQ_Rec, Result);
Res
}]};
{error, Error} -> {error, Error} ->
IQ#iq{type = error, exmpp_iq:error(IQ_Rec, Error)
sub_el = [SubEl, Error]}
end end
end; end;
_ -> _ ->
IQ#iq{type = error, exmpp_iq:error(IQ_Rec, 'bad-request')
sub_el = [SubEl, ?ERR_BAD_REQUEST]}
end
end;
get ->
Node =
string:tokens(xml:get_tag_attr_s("node", SubEl), "/"),
case get_form(Host, From, Node, Lang ,DefEnc) of
{result, Res} ->
IQ#iq{type = result,
sub_el = [{xmlelement, "query",
[{"xmlns", XMLNS}],
Res
}]};
{error, Error} ->
IQ#iq{type = error,
sub_el = [SubEl, Error]}
end end
end. end.
get_form(Host, From, [], Lang, DefEnc) -> get_form(Host, From, [], Lang, DefEnc) ->
#jid{user = User, server = Server, #jid{node = User, domain = Server,
luser = LUser, lserver = LServer} = From, lnode = LUser, ldomain = LServer} = From,
US = {LUser, LServer}, US = {LUser, LServer},
Customs = Customs =
case catch mnesia:dirty_read({irc_custom, {US, Host}}) of case catch mnesia:dirty_read({irc_custom, {US, Host}}) of
{'EXIT', _Reason} -> {'EXIT', _Reason} ->
{error, ?ERR_INTERNAL_SERVER_ERROR}; {error, 'internal-server-error'};
[] -> [] ->
{User, []}; {User, []};
[#irc_custom{data = Data}] -> [#irc_custom{data = Data}] ->
{xml:get_attr_s(username, Data), {proplists:get_value(username, Data, ""),
xml:get_attr_s(encodings, Data)} proplists:get_value(encodings, Data, "")}
end, end,
case Customs of case Customs of
{error, _Error} -> {error, _Error} ->
Customs; Customs;
{Username, Encodings} -> {Username, Encodings} ->
{result, {result,
[{xmlelement, "instructions", [], [#xmlel{ns = ?NS_INBAND_REGISTER, name = 'instructions', children =
[{xmlcdata, [#xmlcdata{cdata = list_to_binary(
translate:translate( translate:translate(
Lang, Lang,
"You need an x:data capable client " "You need an x:data capable client "
"to configure mod_irc settings")}]}, "to configure mod_irc settings"))}]},
{xmlelement, "x", [{"xmlns", ?NS_XDATA}], #xmlel{ns = ?NS_DATA_FORMS, name = 'x', children =
[{xmlelement, "title", [], [#xmlel{ns = ?NS_DATA_FORMS, name = 'title', children =
[{xmlcdata, [#xmlcdata{cdata = list_to_binary(
translate:translate( translate:translate(
Lang, Lang,
"Registration in mod_irc for ") ++ User ++ "@" ++ Server}]}, "Registration in mod_irc for ") ++ User ++ "@" ++ Server)}]},
{xmlelement, "instructions", [], #xmlel{ns = ?NS_DATA_FORMS, name = 'instructions', children =
[{xmlcdata, [#xmlcdata{cdata = list_to_binary(
translate:translate( translate:translate(
Lang, Lang,
"Enter username and encodings you wish to use for " "Enter username and encodings you wish to use for "
"connecting to IRC servers")}]}, "connecting to IRC servers"))}]},
{xmlelement, "field", [{"type", "text-single"}, #xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs = [#xmlattr{name = 'type', value = "text-single"},
{"label", #xmlattr{name = 'label', value =
translate:translate( translate:translate(
Lang, "IRC Username")}, Lang, "IRC Username")},
{"var", "username"}], #xmlattr{name = 'var', value = "username"}], children =
[{xmlelement, "value", [], [{xmlcdata, Username}]}]}, [#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children = [#xmlcdata{cdata = list_to_binary(Username)}]}]},
{xmlelement, "field", [{"type", "fixed"}], #xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs = [#xmlattr{name = 'type', value = "fixed"}], children =
[{xmlelement, "value", [], [#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children =
[{xmlcdata, [#xmlcdata{cdata = list_to_binary(
lists:flatten( lists:flatten(
io_lib:format( io_lib:format(
translate:translate( translate:translate(
@ -471,22 +451,22 @@ get_form(Host, From, [], Lang, DefEnc) ->
"for IRC servers, fill this list with values " "for IRC servers, fill this list with values "
"in format '{\"irc server\", \"encoding\"}'. " "in format '{\"irc server\", \"encoding\"}'. "
"By default this service use \"~s\" encoding."), "By default this service use \"~s\" encoding."),
[DefEnc]))}]}]}, [DefEnc])))}]}]},
{xmlelement, "field", [{"type", "fixed"}], #xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs = [#xmlattr{name = 'type', value = "fixed"}], children =
[{xmlelement, "value", [], [#xmlel{ns = ?NS_DATA_FORMS, name = 'value', children =
[{xmlcdata, [#xmlcdata{cdata = list_to_binary(
translate:translate( translate:translate(
Lang, Lang,
"Example: [{\"irc.lucky.net\", \"koi8-r\"}, " "Example: [{\"irc.lucky.net\", \"koi8-r\"}, "
"{\"vendetta.fef.net\", \"iso8859-1\"}]." "{\"vendetta.fef.net\", \"iso8859-1\"}]."
)}]}]}, ))}]}]},
{xmlelement, "field", [{"type", "text-multi"}, #xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs = [#xmlattr{name = 'type', value = "text-multi"},
{"label", #xmlattr{name = 'label', value =
translate:translate(Lang, "Encodings")}, translate:translate(Lang, "Encodings")},
{"var", "encodings"}], #xmlattr{name = 'var', value = "encodings"}], children =
lists:map( lists:map(
fun(S) -> fun(S) ->
{xmlelement, "value", [], [{xmlcdata, S}]} #xmlel{ns = ?NS_DATA_FORMS, name = 'value', children = [#xmlcdata{cdata = list_to_binary(S)}]}
end, end,
string:tokens( string:tokens(
lists:flatten( lists:flatten(
@ -497,13 +477,13 @@ get_form(Host, From, [], Lang, DefEnc) ->
end; end;
get_form(_Host, _, _, _Lang, _) -> get_form(_Host, _, _, _Lang, _) ->
{error, ?ERR_SERVICE_UNAVAILABLE}. {error, 'service-unavailable'}.
set_form(Host, From, [], _Lang, XData) -> set_form(Host, From, [], _Lang, XData) ->
{LUser, LServer, _} = jlib:jid_tolower(From), {LUser, LServer, _} = jlib:short_prepd_jid(From),
US = {LUser, LServer}, US = {LUser, LServer},
case {lists:keysearch("username", 1, XData), case {lists:keysearch("username", 1, XData),
lists:keysearch("encodings", 1, XData)} of lists:keysearch("encodings", 1, XData)} of
@ -529,26 +509,26 @@ set_form(Host, From, [], _Lang, XData) ->
{atomic, _} -> {atomic, _} ->
{result, []}; {result, []};
_ -> _ ->
{error, ?ERR_NOT_ACCEPTABLE} {error, 'not-acceptable'}
end; end;
_ -> _ ->
{error, ?ERR_NOT_ACCEPTABLE} {error, 'not-acceptable'}
end; end;
_ -> _ ->
{error, ?ERR_NOT_ACCEPTABLE} {error, 'not-acceptable'}
end; end;
_ -> _ ->
{error, ?ERR_NOT_ACCEPTABLE} {error, 'not-acceptable'}
end; end;
set_form(_Host, _, _, _Lang, _XData) -> set_form(_Host, _, _, _Lang, _XData) ->
{error, ?ERR_SERVICE_UNAVAILABLE}. {error, 'service-unavailable'}.
get_user_and_encoding(Host, From, IRCServer, DefEnc) -> get_user_and_encoding(Host, From, IRCServer, DefEnc) ->
#jid{user = User, server = _Server, #jid{node = User, domain = _Server,
luser = LUser, lserver = LServer} = From, lnode = LUser, ldomain = LServer} = From,
US = {LUser, LServer}, US = {LUser, LServer},
case catch mnesia:dirty_read({irc_custom, {US, Host}}) of case catch mnesia:dirty_read({irc_custom, {US, Host}}) of
{'EXIT', _Reason} -> {'EXIT', _Reason} ->
@ -556,8 +536,8 @@ get_user_and_encoding(Host, From, IRCServer, DefEnc) ->
[] -> [] ->
{User, DefEnc}; {User, DefEnc};
[#irc_custom{data = Data}] -> [#irc_custom{data = Data}] ->
{xml:get_attr_s(username, Data), {proplists:get_value(username, Data, ""),
case xml:get_attr_s(IRCServer, xml:get_attr_s(encodings, Data)) of case proplists:get_value(IRCServer, proplists:get_value(encodings, Data, ""), "") of
"" -> DefEnc; "" -> DefEnc;
E -> E E -> E
end} end}

View File

@ -43,8 +43,9 @@
terminate/3, terminate/3,
code_change/4]). code_change/4]).
-include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("jlib.hrl").
-define(SETS, gb_sets). -define(SETS, gb_sets).
@ -122,8 +123,8 @@ open_socket(init, StateData) ->
{error, Reason} -> {error, Reason} ->
?DEBUG("connect return ~p~n", [Reason]), ?DEBUG("connect return ~p~n", [Reason]),
Text = case Reason of Text = case Reason of
timeout -> "Server Connect Timeout"; timeout -> <<"Server Connect Timeout">>;
_ -> "Server Connect Failed" _ -> <<"Server Connect Failed">>
end, end,
bounce_messages(Text), bounce_messages(Text),
{stop, normal, StateData} {stop, normal, StateData}
@ -197,22 +198,22 @@ code_change(_OldVsn, StateName, StateData, _Extra) ->
%% {stop, Reason, NewStateData} %% {stop, Reason, NewStateData}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
handle_info({route_chan, Channel, Resource, handle_info({route_chan, Channel, Resource,
{xmlelement, "presence", Attrs, _Els}}, El},
StateName, StateData) -> StateName, StateData) when ?IS_PRESENCE(El) ->
NewStateData = NewStateData =
case xml:get_attr_s("type", Attrs) of case exmpp_presence:get_type(El) of
"unavailable" -> 'unavailable' ->
S1 = ?SEND(io_lib:format("PART #~s\r\n", [Channel])), S1 = ?SEND(io_lib:format("PART #~s\r\n", [Channel])),
S1#state{channels = S1#state{channels =
dict:erase(Channel, S1#state.channels)}; dict:erase(Channel, S1#state.channels)};
"subscribe" -> StateData; 'subscribe' -> StateData;
"subscribed" -> StateData; 'subscribed' -> StateData;
"unsubscribe" -> StateData; 'unsubscribe' -> StateData;
"unsubscribed" -> StateData; 'unsubscribed' -> StateData;
"error" -> stop; 'error' -> stop;
_ -> _ ->
Nick = case Resource of Nick = case Resource of
"" -> undefined ->
StateData#state.nick; StateData#state.nick;
_ -> _ ->
Resource Resource
@ -243,20 +244,20 @@ handle_info({route_chan, Channel, Resource,
end; end;
handle_info({route_chan, Channel, Resource, handle_info({route_chan, Channel, Resource,
{xmlelement, "message", Attrs, _Els} = El}, El},
StateName, StateData) -> StateName, StateData) when ?IS_MESSAGE(El) ->
NewStateData = NewStateData =
case xml:get_attr_s("type", Attrs) of case exmpp_message:get_type(El) of
"groupchat" -> 'groupchat' ->
case xml:get_path_s(El, [{elem, "subject"}, cdata]) of case exmpp_message:get_subject(El) of
"" -> undefined ->
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid( exmpp_jid:make_jid(
lists:concat( lists:concat(
[Channel, "%", StateData#state.server]), [Channel, "%", StateData#state.server]),
StateData#state.host, StateData#state.nick), StateData#state.host, StateData#state.nick),
StateData#state.user, El), StateData#state.user, El),
Body = xml:get_path_s(El, [{elem, "body"}, cdata]), Body = binary_to_list(exmpp_message:get_body(El)),
case Body of case Body of
"/quote " ++ Rest -> "/quote " ++ Rest ->
?SEND(Rest ++ "\r\n"); ?SEND(Rest ++ "\r\n");
@ -309,8 +310,8 @@ handle_info({route_chan, Channel, Resource,
end, Strings)), end, Strings)),
?SEND(Res) ?SEND(Res)
end; end;
Type when Type == "chat"; Type == ""; Type == "normal" -> Type when Type == 'chat'; Type == 'normal' ->
Body = xml:get_path_s(El, [{elem, "body"}, cdata]), Body = binary_to_list(exmpp_message:get_body(El)),
case Body of case Body of
"/quote " ++ Rest -> "/quote " ++ Rest ->
?SEND(Rest ++ "\r\n"); ?SEND(Rest ++ "\r\n");
@ -351,7 +352,7 @@ handle_info({route_chan, Channel, Resource,
end, Strings)), end, Strings)),
?SEND(Res) ?SEND(Res)
end; end;
"error" -> 'error' ->
stop; stop;
_ -> _ ->
StateData StateData
@ -365,38 +366,34 @@ handle_info({route_chan, Channel, Resource,
handle_info({route_chan, Channel, Resource, handle_info({route_chan, Channel, Resource,
{xmlelement, "iq", _Attrs, _Els} = El}, El},
StateName, StateData) -> StateName, StateData) when ?IS_IQ(El) ->
From = StateData#state.user, From = StateData#state.user,
To = jlib:make_jid(lists:concat([Channel, "%", StateData#state.server]), To = exmpp_jid:make_jid(lists:concat([Channel, "%", StateData#state.server]),
StateData#state.host, StateData#state.nick), StateData#state.host, StateData#state.nick),
case jlib:iq_query_info(El) of case exmpp_iq:xmlel_to_iq(El) of
#iq{xmlns = ?NS_MUC_ADMIN} = IQ -> #iq{kind = request, ns = ?NS_MUC_ADMIN} = IQ_Rec ->
iq_admin(StateData, Channel, From, To, IQ); iq_admin(StateData, Channel, From, To, IQ_Rec);
#iq{xmlns = ?NS_VERSION} -> #iq{kind = request, ns = ?NS_SOFT_VERSION} ->
Res = io_lib:format("PRIVMSG ~s :\001VERSION\001\r\n", Res = io_lib:format("PRIVMSG ~s :\001VERSION\001\r\n",
[Resource]), [Resource]),
?SEND(Res), ?SEND(Res),
Err = jlib:make_error_reply( Err = exmpp_iq:error(El, 'feature-not-implemented'),
El, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
#iq{xmlns = ?NS_TIME} -> #iq{kind = request, ns = ?NS_TIME_OLD} ->
Res = io_lib:format("PRIVMSG ~s :\001TIME\001\r\n", Res = io_lib:format("PRIVMSG ~s :\001TIME\001\r\n",
[Resource]), [Resource]),
?SEND(Res), ?SEND(Res),
Err = jlib:make_error_reply( Err = exmpp_iq:error(El, 'feature-not-implemented'),
El, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
#iq{xmlns = ?NS_VCARD} -> #iq{kind = request, ns = ?NS_VCARD} ->
Res = io_lib:format("WHOIS ~s \r\n", Res = io_lib:format("WHOIS ~s \r\n",
[Resource]), [Resource]),
?SEND(Res), ?SEND(Res),
Err = jlib:make_error_reply( Err = exmpp_iq:error(El, 'feature-not-implemented'),
El, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
#iq{} -> #iq{} ->
Err = jlib:make_error_reply( Err = exmpp_iq:error(El, 'feature-not-implemented'),
El, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(To, From, Err); ejabberd_router:route(To, From, Err);
_ -> _ ->
ok ok
@ -408,12 +405,12 @@ handle_info({route_chan, _Channel, _Resource, _Packet}, StateName, StateData) ->
handle_info({route_nick, Nick, handle_info({route_nick, Nick,
{xmlelement, "message", Attrs, _Els} = El}, El},
StateName, StateData) -> StateName, StateData) when ?IS_MESSAGE(El) ->
NewStateData = NewStateData =
case xml:get_attr_s("type", Attrs) of case exmpp_message:get_type(El) of
"chat" -> 'chat' ->
Body = xml:get_path_s(El, [{elem, "body"}, cdata]), Body = binary_to_list(exmpp_message:get_body(El)),
case Body of case Body of
"/quote " ++ Rest -> "/quote " ++ Rest ->
?SEND(Rest ++ "\r\n"); ?SEND(Rest ++ "\r\n");
@ -451,7 +448,7 @@ handle_info({route_nick, Nick,
end, Strings)), end, Strings)),
?SEND(Res) ?SEND(Res)
end; end;
"error" -> 'error' ->
stop; stop;
_ -> _ ->
StateData StateData
@ -585,17 +582,17 @@ terminate(_Reason, _StateName, StateData) ->
mod_irc:closed_connection(StateData#state.host, mod_irc:closed_connection(StateData#state.host,
StateData#state.user, StateData#state.user,
StateData#state.server), StateData#state.server),
bounce_messages("Server Connect Failed"), bounce_messages(<<"Server Connect Failed">>),
lists:foreach( lists:foreach(
fun(Chan) -> fun(Chan) ->
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid( exmpp_jid:make_jid(
lists:concat([Chan, "%", StateData#state.server]), lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, StateData#state.nick), StateData#state.host, StateData#state.nick),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [{"type", "error"}], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', attrs = [#xmlattr{name = 'type', value = "error"}], children =
[{xmlelement, "error", [{"code", "502"}], [#xmlel{ns = ?NS_JABBER_CLIENT, name = 'error', attrs = [#xmlattr{name = 'code', value = "502"}], children =
[{xmlcdata, "Server Connect Failed"}]}]}) [#xmlcdata{cdata = <<"Server Connect Failed">>}]}]})
end, dict:fetch_keys(StateData#state.channels)), end, dict:fetch_keys(StateData#state.channels)),
case StateData#state.socket of case StateData#state.socket of
undefined -> undefined ->
@ -627,15 +624,16 @@ send_text(#state{socket = Socket, encoding = Encoding}, Text) ->
bounce_messages(Reason) -> bounce_messages(Reason) ->
receive receive
{send_element, El} -> {send_element, El} ->
{xmlelement, _Name, Attrs, _SubTags} = El, case exmpp_stanza:get_type(El) of
case xml:get_attr_s("type", Attrs) of
"error" -> "error" ->
ok; ok;
_ -> _ ->
Err = jlib:make_error_reply(El, Error = #xmlel{ns = ?NS_JABBER_CLIENT, name = 'error',
"502", Reason), attrs = [#xmlattr{name = 'code', value = "502"}],
From = jlib:string_to_jid(xml:get_attr_s("from", Attrs)), children = [#xmlcdata{cdata = Reason}]},
To = jlib:string_to_jid(xml:get_attr_s("to", Attrs)), Err = exmpp_stanza:reply_with_error(El, Error),
From = exmpp_jid:list_to_jid(exmpp_stanza:get_sender(El)),
To = exmpp_jid:list_to_jid(exmpp_stanza:get_recipient(El)),
ejabberd_router:route(To, From, Err) ejabberd_router:route(To, From, Err)
end, end,
bounce_messages(Reason) bounce_messages(Reason)
@ -688,15 +686,14 @@ process_channel_list_user(StateData, Chan, User) ->
_ -> {User1, "member", "participant"} _ -> {User1, "member", "participant"}
end, end,
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, User2), StateData#state.host, User2),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', children =
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [#xmlel{ns = ?NS_MUC_USER, name = 'x', children =
[{xmlelement, "item", [#xmlel{ns = ?NS_MUC_USER, name = 'item', attrs =
[{"affiliation", Affiliation}, [#xmlattr{name = 'affiliation', value = Affiliation},
{"role", Role}], #xmlattr{name = 'role', value = Role}]}]}]}),
[]}]}]}),
case catch dict:update(Chan, case catch dict:update(Chan,
fun(Ps) -> fun(Ps) ->
?SETS:add_element(User2, Ps) ?SETS:add_element(User2, Ps)
@ -712,14 +709,11 @@ process_channel_topic(StateData, Chan, String) ->
{ok, Msg, _} = regexp:sub(String, ".*332[^:]*:", ""), {ok, Msg, _} = regexp:sub(String, ".*332[^:]*:", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid( exmpp_jid:make_jid(
lists:concat([Chan, "%", StateData#state.server]), lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}], exmpp_message:groupchat(Msg1, "Topic for #" ++ Chan ++ ": " ++ Msg1)).
[{xmlelement, "subject", [], [{xmlcdata, Msg1}]},
{xmlelement, "body", [], [{xmlcdata, "Topic for #" ++ Chan ++ ": " ++ Msg1}]}
]}).
process_channel_topic_who(StateData, Chan, String) -> process_channel_topic_who(StateData, Chan, String) ->
Words = string:tokens(String, " "), Words = string:tokens(String, " "),
@ -740,55 +734,47 @@ process_channel_topic_who(StateData, Chan, String) ->
Msg2 = filter_message(Msg1), Msg2 = filter_message(Msg1),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}], exmpp_message:groupchat(Msg2)).
[{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
process_endofwhois(StateData, _String, Nick) -> process_endofwhois(StateData, _String, Nick) ->
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Nick, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "chat"}], exmpp_message:chat("End of WHOIS")).
[{xmlelement, "body", [], [{xmlcdata, "End of WHOIS"}]}]}).
process_whois311(StateData, String, Nick, Ident, Irchost) -> process_whois311(StateData, String, Nick, Ident, Irchost) ->
{ok, Fullname, _} = regexp:sub(String, ".*311[^:]*:", ""), {ok, Fullname, _} = regexp:sub(String, ".*311[^:]*:", ""),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Nick, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "chat"}], exmpp_message:chat(lists:concat(
[{xmlelement, "body", [],
[{xmlcdata, lists:concat(
["WHOIS: ", Nick, " is ", ["WHOIS: ", Nick, " is ",
Ident, "@" , Irchost, " : " , Fullname])}]}]}). Ident, "@" , Irchost, " : " , Fullname]))).
process_whois312(StateData, String, Nick, Ircserver) -> process_whois312(StateData, String, Nick, Ircserver) ->
{ok, Ircserverdesc, _} = regexp:sub(String, ".*312[^:]*:", ""), {ok, Ircserverdesc, _} = regexp:sub(String, ".*312[^:]*:", ""),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Nick, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "chat"}], exmpp_message:chat(lists:concat(["WHOIS: ", Nick, " use ",
[{xmlelement, "body", [], Ircserver, " : ", Ircserverdesc]))).
[{xmlcdata, lists:concat(["WHOIS: ", Nick, " use ",
Ircserver, " : ", Ircserverdesc])}]}]}).
process_whois319(StateData, String, Nick) -> process_whois319(StateData, String, Nick) ->
{ok, Chanlist, _} = regexp:sub(String, ".*319[^:]*:", ""), {ok, Chanlist, _} = regexp:sub(String, ".*319[^:]*:", ""),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Nick, "!", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Nick, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, ""),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "chat"}], exmpp_message:chat(lists:concat(["WHOIS: ", Nick, " is on ",
[{xmlelement, "body", [], Chanlist]))).
[{xmlcdata, lists:concat(["WHOIS: ", Nick, " is on ",
Chanlist])}]}]}).
@ -803,11 +789,10 @@ process_chanprivmsg(StateData, Chan, From, String) ->
end, end,
Msg2 = filter_message(Msg1), Msg2 = filter_message(Msg1),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, FromUser), StateData#state.host, FromUser),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}], exmpp_message:groupchat(Msg2)).
[{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
@ -822,11 +807,10 @@ process_channotice(StateData, Chan, From, String) ->
end, end,
Msg2 = filter_message(Msg1), Msg2 = filter_message(Msg1),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, FromUser), StateData#state.host, FromUser),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}], exmpp_message:groupchat(Msg2)).
[{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
@ -842,11 +826,10 @@ process_privmsg(StateData, _Nick, From, String) ->
end, end,
Msg2 = filter_message(Msg1), Msg2 = filter_message(Msg1),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([FromUser, "!", StateData#state.server]), exmpp_jid:make_jid(lists:concat([FromUser, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, undefined),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "chat"}], exmpp_message:chat(Msg2)).
[{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
process_notice(StateData, _Nick, From, String) -> process_notice(StateData, _Nick, From, String) ->
@ -860,11 +843,10 @@ process_notice(StateData, _Nick, From, String) ->
end, end,
Msg2 = filter_message(Msg1), Msg2 = filter_message(Msg1),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([FromUser, "!", StateData#state.server]), exmpp_jid:make_jid(lists:concat([FromUser, "!", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, undefined),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "chat"}], exmpp_message:chat(Msg2)).
[{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
process_version(StateData, _Nick, From) -> process_version(StateData, _Nick, From) ->
@ -889,7 +871,7 @@ process_userinfo(StateData, _Nick, From) ->
"xmpp:~s" "xmpp:~s"
"\001\r\n", "\001\r\n",
[FromUser, [FromUser,
jlib:jid_to_string(StateData#state.user)])). exmpp_jid:jid_to_list(StateData#state.user)])).
process_topic(StateData, Chan, From, String) -> process_topic(StateData, Chan, From, String) ->
@ -897,31 +879,27 @@ process_topic(StateData, Chan, From, String) ->
{ok, Msg, _} = regexp:sub(String, ".*TOPIC[^:]*:", ""), {ok, Msg, _} = regexp:sub(String, ".*TOPIC[^:]*:", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, FromUser), StateData#state.host, FromUser),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}], exmpp_message:groupchat(Msg1,
[{xmlelement, "subject", [], [{xmlcdata, Msg1}]}, "/me has changed the subject to: " ++ Msg1)).
{xmlelement, "body", [],
[{xmlcdata, "/me has changed the subject to: " ++
Msg1}]}]}).
process_part(StateData, Chan, From, String) -> process_part(StateData, Chan, From, String) ->
[FromUser | FromIdent] = string:tokens(From, "!"), [FromUser | FromIdent] = string:tokens(From, "!"),
{ok, Msg, _} = regexp:sub(String, ".*PART[^:]*:", ""), {ok, Msg, _} = regexp:sub(String, ".*PART[^:]*:", ""),
Msg1 = filter_message(Msg), Msg1 = filter_message(Msg),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, FromUser), StateData#state.host, FromUser),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', attrs = [#xmlattr{name = 'type', value = "unavailable"}], children =
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [#xmlel{ns = ?NS_MUC_USER, name = 'x', children =
[{xmlelement, "item", [#xmlel{ns = ?NS_MUC_USER, name = 'item', attrs =
[{"affiliation", "member"}, [#xmlattr{name = 'affiliation', value = "member"},
{"role", "none"}], #xmlattr{name = 'role', value = "none"}]}]},
[]}]}, #xmlel{ns = ?NS_MUC_USER, name = 'status', children =
{xmlelement, "status", [], [#xmlcdata{cdata = list_to_binary(Msg1 ++ " (" ++ FromIdent ++ ")")}]}]
[{xmlcdata, Msg1 ++ " (" ++ FromIdent ++ ")"}]}]
}), }),
case catch dict:update(Chan, case catch dict:update(Chan,
fun(Ps) -> fun(Ps) ->
@ -945,18 +923,17 @@ process_quit(StateData, From, String) ->
case ?SETS:is_member(FromUser, Ps) of case ?SETS:is_member(FromUser, Ps) of
true -> true ->
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid( exmpp_jid:make_jid(
lists:concat([Chan, "%", StateData#state.server]), lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, FromUser), StateData#state.host, FromUser),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', attrs = [#xmlattr{name = 'type', value = "unavailable"}], children =
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [#xmlel{ns = ?NS_MUC_USER, name = 'x', children =
[{xmlelement, "item", [#xmlel{ns = ?NS_MUC_USER, name = 'item', attrs =
[{"affiliation", "member"}, [#xmlattr{name = 'affiliation', value = "member"},
{"role", "none"}], #xmlattr{name = 'role', value = "none"}]}]},
[]}]}, #xmlel{ns = ?NS_MUC_USER, name = 'status', children =
{xmlelement, "status", [], [#xmlcdata{cdata = list_to_binary(Msg1 ++ " (" ++ FromIdent ++ ")")}]}
[{xmlcdata, Msg1 ++ " (" ++ FromIdent ++ ")"}]}
]}), ]}),
remove_element(FromUser, Ps); remove_element(FromUser, Ps);
_ -> _ ->
@ -970,17 +947,16 @@ process_join(StateData, Channel, From, _String) ->
[FromUser | FromIdent] = string:tokens(From, "!"), [FromUser | FromIdent] = string:tokens(From, "!"),
Chan = lists:subtract(Channel, ":#"), Chan = lists:subtract(Channel, ":#"),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, FromUser), StateData#state.host, FromUser),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', children =
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [#xmlel{ns = ?NS_MUC_USER, name = 'x', children =
[{xmlelement, "item", [#xmlel{ns = ?NS_MUC_USER, name = 'item', attrs =
[{"affiliation", "member"}, [#xmlattr{name = 'affiliation', value = "member"},
{"role", "participant"}], #xmlattr{name = 'role', value = "participant"}]}]},
[]}]}, #xmlel{ns = ?NS_MUC_USER, name = 'status', children =
{xmlelement, "status", [], [#xmlcdata{cdata = list_to_binary(FromIdent)}]}]}),
[{xmlcdata, FromIdent}]}]}),
case catch dict:update(Chan, case catch dict:update(Chan,
fun(Ps) -> fun(Ps) ->
@ -997,36 +973,33 @@ process_join(StateData, Channel, From, _String) ->
process_mode_o(StateData, Chan, _From, Nick, Affiliation, Role) -> process_mode_o(StateData, Chan, _From, Nick, Affiliation, Role) ->
%Msg = lists:last(string:tokens(String, ":")), %Msg = lists:last(string:tokens(String, ":")),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, Nick), StateData#state.host, Nick),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', children =
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [#xmlel{ns = ?NS_MUC_USER, name = 'x', children =
[{xmlelement, "item", [#xmlel{ns = ?NS_MUC_USER, name = 'item', attrs =
[{"affiliation", Affiliation}, [#xmlattr{name = 'affiliation', value = Affiliation},
{"role", Role}], #xmlattr{name = 'role', value = Role}]}]}]}).
[]}]}]}).
process_kick(StateData, Chan, From, Nick, String) -> process_kick(StateData, Chan, From, Nick, String) ->
Msg = lists:last(string:tokens(String, ":")), Msg = lists:last(string:tokens(String, ":")),
Msg2 = Nick ++ " kicked by " ++ From ++ " (" ++ filter_message(Msg) ++ ")", Msg2 = Nick ++ " kicked by " ++ From ++ " (" ++ filter_message(Msg) ++ ")",
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, ""), StateData#state.host, undefined),
StateData#state.user, StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}], exmpp_message:groupchat(Msg2)),
[{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), exmpp_jid:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, Nick), StateData#state.host, Nick),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', attrs = [#xmlattr{name = 'type', value = "unavailable"}], children =
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [#xmlel{ns = ?NS_MUC_USER, name = 'x', children =
[{xmlelement, "item", [#xmlel{ns = ?NS_MUC_USER, name = 'item', attrs =
[{"affiliation", "none"}, [#xmlattr{name = 'affiliation', value = "none"},
{"role", "none"}], #xmlattr{name = 'role', value = "none"}]},
[]}, #xmlel{ns = ?NS_MUC_USER, name = 'status', attrs = [#xmlattr{name = 'code', value = "307"}]}
{xmlelement, "status", [{"code", "307"}], []}
]}]}). ]}]}).
process_nick(StateData, From, NewNick) -> process_nick(StateData, From, NewNick) ->
@ -1038,30 +1011,28 @@ process_nick(StateData, From, NewNick) ->
case ?SETS:is_member(FromUser, Ps) of case ?SETS:is_member(FromUser, Ps) of
true -> true ->
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid( exmpp_jid:make_jid(
lists:concat([Chan, "%", StateData#state.server]), lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, FromUser), StateData#state.host, FromUser),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', attrs = [#xmlattr{name = 'type', value = "unavailable"}], children =
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [#xmlel{ns = ?NS_MUC_USER, name = 'x', children =
[{xmlelement, "item", [#xmlel{ns = ?NS_MUC_USER, name = 'item', attrs =
[{"affiliation", "member"}, [#xmlattr{name = 'affiliation', value = "member"},
{"role", "participant"}, #xmlattr{name = 'role', value = "participant"},
{"nick", Nick}], #xmlattr{name = 'nick', value = Nick}]},
[]}, #xmlel{ns = ?NS_MUC_USER, name = 'status', attrs = [#xmlattr{name = 'code', value = "303"}]}
{xmlelement, "status", [{"code", "303"}], []}
]}]}), ]}]}),
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid( exmpp_jid:make_jid(
lists:concat([Chan, "%", StateData#state.server]), lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, Nick), StateData#state.host, Nick),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', children =
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [#xmlel{ns = ?NS_MUC_USER, name = 'x', children =
[{xmlelement, "item", [#xmlel{ns = ?NS_MUC_USER, name = 'item', attrs =
[{"affiliation", "member"}, [#xmlattr{name = 'affiliation', value = "member"},
{"role", "participant"}], #xmlattr{name = 'role', value = "participant"}]}
[]}
]}]}), ]}]}),
?SETS:add_element(Nick, ?SETS:add_element(Nick,
remove_element(FromUser, Ps)); remove_element(FromUser, Ps));
@ -1076,13 +1047,13 @@ process_error(StateData, String) ->
lists:foreach( lists:foreach(
fun(Chan) -> fun(Chan) ->
ejabberd_router:route( ejabberd_router:route(
jlib:make_jid( exmpp_jid:make_jid(
lists:concat([Chan, "%", StateData#state.server]), lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, StateData#state.nick), StateData#state.host, StateData#state.nick),
StateData#state.user, StateData#state.user,
{xmlelement, "presence", [{"type", "error"}], #xmlel{ns = ?NS_JABBER_CLIENT, name = 'presence', attrs = [#xmlattr{name = 'type', value = "error"}], children =
[{xmlelement, "error", [{"code", "502"}], [#xmlel{ns = ?NS_JABBER_CLIENT, name = 'error', attrs = [#xmlattr{name = 'code', value = "502"}], children =
[{xmlcdata, String}]}]}) [#xmlcdata{cdata = list_to_binary(String)}]}]})
end, dict:fetch_keys(StateData#state.channels)). end, dict:fetch_keys(StateData#state.channels)).
@ -1099,7 +1070,7 @@ remove_element(E, Set) ->
iq_admin(StateData, Channel, From, To, iq_admin(StateData, Channel, From, To,
#iq{type = Type, xmlns = XMLNS, sub_el = SubEl} = IQ) -> #iq{type = Type, ns = XMLNS, payload = SubEl} = IQ_Rec) ->
case catch process_iq_admin(StateData, Channel, Type, SubEl) of case catch process_iq_admin(StateData, Channel, Type, SubEl) of
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]); ?ERROR_MSG("~p", [Reason]);
@ -1108,17 +1079,14 @@ iq_admin(StateData, Channel, From, To,
Res /= ignore -> Res /= ignore ->
ResIQ = case Res of ResIQ = case Res of
{result, ResEls} -> {result, ResEls} ->
IQ#iq{type = result, Result = #xmlel{ns = XMLNS, name = 'query',
sub_el = [{xmlelement, "query", children = ResEls},
[{"xmlns", XMLNS}], exmpp_iq:result(IQ_Rec, Result);
ResEls
}]};
{error, Error} -> {error, Error} ->
IQ#iq{type = error, exmpp_iq:error(IQ_Rec, Error)
sub_el = [SubEl, Error]}
end, end,
ejabberd_router:route(To, From, ejabberd_router:route(To, From,
jlib:iq_to_xml(ResIQ)); exmpp_iq:iq_to_xmlel(ResIQ));
true -> true ->
ok ok
end end
@ -1126,23 +1094,23 @@ iq_admin(StateData, Channel, From, To,
process_iq_admin(StateData, Channel, set, SubEl) -> process_iq_admin(StateData, Channel, set, SubEl) ->
case xml:get_subtag(SubEl, "item") of case exmpp_xml:get_element(SubEl, 'item') of
false -> false ->
{error, ?ERR_BAD_REQUEST}; {error, 'bad-request'};
ItemEl -> ItemEl ->
Nick = xml:get_tag_attr_s("nick", ItemEl), Nick = exmpp_xml:get_attribute(ItemEl, 'nick', ""),
Affiliation = xml:get_tag_attr_s("affiliation", ItemEl), Affiliation = exmpp_xml:get_attribute(ItemEl, 'affiliation', ""),
Role = xml:get_tag_attr_s("role", ItemEl), Role = exmpp_xml:get_attribute(ItemEl, 'role', ""),
Reason = xml:get_path_s(ItemEl, [{elem, "reason"}, cdata]), Reason = exmpp_xml:get_path(ItemEl, [{element, 'reason'}, cdata_as_list]),
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, ?ERR_FEATURE_NOT_IMPLEMENTED}. {error, 'feature-not-implemented'}.
process_admin(_StateData, _Channel, "", _Affiliation, _Role, _Reason) -> process_admin(_StateData, _Channel, "", _Affiliation, _Role, _Reason) ->
{error, ?ERR_FEATURE_NOT_IMPLEMENTED}; {error, '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
@ -1160,7 +1128,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, ?ERR_FEATURE_NOT_IMPLEMENTED}. {error, 'feature-not-implemented'}.