From ada531bd8dbdb25699d545354d209196e2615ddc Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 16 Jun 2009 17:48:13 +0000 Subject: [PATCH] Started code clean-up (EJAB-936)(thanks to Michael Remond) SVN Revision: 2255 --- src/web/ejabberd_http_bind.erl | 291 +++++++++++++++------------------ 1 file changed, 129 insertions(+), 162 deletions(-) diff --git a/src/web/ejabberd_http_bind.erl b/src/web/ejabberd_http_bind.erl index 11431ab6e..4f3648a9b 100644 --- a/src/web/ejabberd_http_bind.erl +++ b/src/web/ejabberd_http_bind.erl @@ -1,10 +1,10 @@ %%%---------------------------------------------------------------------- %%% File : ejabberd_http_bind.erl %%% Author : Stefan Strigler -%%% Purpose : Implements XMPP over BOSH (XEP-0205) (formerly known as +%%% Purpose : Implements XMPP over BOSH (XEP-0205) (formerly known as %%% HTTP Binding) %%% Created : 21 Sep 2005 by Stefan Strigler -%%% Id : $Id: ejabberd_http_bind.erl 953 2009-05-07 10:40:40Z alexey $ +%%% Id : $Id: ejabberd_http_bind.erl 958 2009-05-12 14:43:41Z mremond $ %%%---------------------------------------------------------------------- -module(ejabberd_http_bind). @@ -22,7 +22,7 @@ terminate/3, send/2, setopts/2, - sockname/1, + sockname/1, peername/1, controlling_process/2, close/1, @@ -84,7 +84,7 @@ -define(MAX_WAIT, 3600). % max num of secs to keep a request on hold -define(MAX_INACTIVITY, 30000). % msecs to wait before terminating % idle sessions --define(MAX_PAUSE, 120). % may num of sec a client is allowed to pause +-define(MAX_PAUSE, 120). % may num of sec a client is allowed to pause % the session -define(CT, {"Content-Type", "text/xml; charset=utf-8"}). @@ -135,6 +135,7 @@ process_request(Data, IP) -> {ok, {"", Rid, Attrs, Payload}} -> case xml:get_attr_s("to",Attrs) of "" -> + ?ERROR_MSG("Session not created (Improper addressing)", []), {200, ?HEADER, ""}; @@ -152,7 +153,7 @@ process_request(Data, IP) -> end; {ok, {Sid, Rid, Attrs, Payload1}} -> %% old session - StreamStart = + StreamStart = case xml:get_attr_s("xmpp:restart",Attrs) of "true" -> true; @@ -168,38 +169,35 @@ process_request(Data, IP) -> end, handle_http_put(Sid, Rid, Attrs, Payload2, StreamStart, IP); _ -> + ?ERROR_MSG("Received bad request: ~p", [Data]), {400, ?HEADER, ""} end. handle_session_start(Pid, XmppDomain, Sid, Rid, Attrs, Payload, IP) -> ?DEBUG("got pid: ~p", [Pid]), - Wait = case - string:to_integer(xml:get_attr_s("wait",Attrs)) - of + Wait = case string:to_integer(xml:get_attr_s("wait",Attrs)) of {error, _} -> ?MAX_WAIT; {CWait, _} -> - if + if (CWait > ?MAX_WAIT) -> ?MAX_WAIT; true -> CWait end end, - Hold = case - string:to_integer(xml:get_attr_s("hold",Attrs)) - of + Hold = case string:to_integer(xml:get_attr_s("hold",Attrs)) of {error, _} -> (?MAX_REQUESTS - 1); {CHold, _} -> - if + if (CHold > (?MAX_REQUESTS - 1)) -> (?MAX_REQUESTS - 1); true -> CHold end end, - Version = + Version = case catch list_to_float( xml:get_attr_s("ver", Attrs)) of {'EXIT', _} -> 0.0; @@ -211,7 +209,7 @@ handle_session_start(Pid, XmppDomain, Sid, Rid, Attrs, Payload, IP) -> mnesia:write( #http_bind{id = Sid, pid = Pid, - to = {XmppDomain, + to = {XmppDomain, XmppVersion}, hold = Hold, wait = Wait, @@ -229,7 +227,7 @@ handle_session_start(Pid, XmppDomain, Sid, Rid, Attrs, Payload, IP) -> %% Returns: {ok, StateName, StateData} | %% {ok, StateName, StateData, Timeout} | %% ignore | -%% {stop, StopReason} +%% {stop, StopReason} %%---------------------------------------------------------------------- init([Sid, Key, IP]) -> ?DEBUG("started: ~p", [{Sid, Key, IP}]), @@ -255,7 +253,7 @@ init([Sid, Key, IP]) -> %% Func: StateName/2 %% Returns: {next_state, NextStateName, NextStateData} | %% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} +%% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- @@ -266,7 +264,7 @@ init([Sid, Key, IP]) -> %% {reply, Reply, NextStateName, NextStateData} | %% {reply, Reply, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} +%% {stop, Reason, Reply, NewStateData} %%---------------------------------------------------------------------- %state_name(Event, From, StateData) -> % Reply = ok, @@ -276,7 +274,7 @@ init([Sid, Key, IP]) -> %% Func: handle_event/3 %% Returns: {next_state, NextStateName, NextStateData} | %% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} +%% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- handle_event({activate, From}, StateName, StateData) -> case StateData#state.input of @@ -302,19 +300,14 @@ handle_event(_Event, StateName, StateData) -> %% {reply, Reply, NextStateName, NextStateData} | %% {reply, Reply, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} +%% {stop, Reason, Reply, NewStateData} %%---------------------------------------------------------------------- handle_sync_event({send, Packet}, _From, StateName, StateData) -> Output = [StateData#state.output | Packet], if StateData#state.http_receiver /= undefined -> - if - StateData#state.timer /= undefined -> - cancel_timer(StateData#state.timer); - true -> - ok - end, - Timer = if + cancel_timer(StateData#state.timer), + Timer = if StateData#state.pause > 0 -> erlang:start_timer( StateData#state.pause*1000, self(), []); @@ -329,12 +322,7 @@ handle_sync_event({send, Packet}, _From, StateName, StateData) -> {ok, Output} end, gen_fsm:reply(StateData#state.http_receiver, HTTPReply), - if - StateData#state.wait_timer /= undefined -> - cancel_timer(StateData#state.wait_timer); - true -> - ok - end, + cancel_timer(StateData#state.wait_timer), Reply = ok, {reply, Reply, StateName, StateData#state{output = [], @@ -354,9 +342,9 @@ handle_sync_event(stop, _From, _StateName, StateData) -> handle_sync_event({http_put, Rid, Attrs, _Payload, Hold, _StreamTo, _IP}=Request, _From, StateName, StateData) -> %% Check if Rid valid - RidAllow = + RidAllow = case StateData#state.rid of - none -> + none -> %% First request - nothing saved so far {true, 0}; OldRid -> @@ -375,17 +363,17 @@ handle_sync_event({http_put, Rid, Attrs, _Payload, Hold, _StreamTo, _IP}=Request {true, 0} end; %% We have missed packets, we need to cached it to process it later on: - (OldRid < Rid) and + (OldRid < Rid) and (Rid =< (OldRid + Hold + 1)) -> buffer; - (Rid =< OldRid) and + (Rid =< OldRid) and (Rid > OldRid - Hold - 1) -> repeat; true -> false end end, - + %% Check if Rid is in sequence or out of sequence: case RidAllow of buffer -> @@ -409,19 +397,14 @@ handle_sync_event({http_get, Rid, Wait, Hold}, From, StateName, StateData) -> true -> ok end, - if - StateData#state.wait_timer /= undefined -> - cancel_timer(StateData#state.wait_timer); - true -> - ok - end, + cancel_timer(StateData#state.wait_timer), {TMegSec, TSec, TMSec} = now(), TNow = (TMegSec * 1000000 + TSec) * 1000000 + TMSec, - if - (Hold > 0) and - (StateData#state.output == "") and - ((TNow - StateData#state.ctime) < (Wait*1000*1000)) and - (StateData#state.rid == Rid) and + if + (Hold > 0) and + (StateData#state.output == "") and + ((TNow - StateData#state.ctime) < (Wait*1000*1000)) and + (StateData#state.rid == Rid) and (StateData#state.input /= "cancel") and (StateData#state.pause == 0) -> WaitTimer = erlang:start_timer(Wait * 1000, self(), []), @@ -430,13 +413,8 @@ handle_sync_event({http_get, Rid, Wait, Hold}, From, StateName, StateData) -> wait_timer = WaitTimer, timer = undefined}}; (StateData#state.input == "cancel") -> - if - StateData#state.timer /= undefined -> - cancel_timer(StateData#state.timer); - true -> - ok - end, - Timer = if + cancel_timer(StateData#state.timer), + Timer = if StateData#state.pause > 0 -> erlang:start_timer( StateData#state.pause*1000, self(), []); @@ -451,13 +429,8 @@ handle_sync_event({http_get, Rid, Wait, Hold}, From, StateName, StateData) -> wait_timer = undefined, timer = Timer}}; true -> - if - StateData#state.timer /= undefined -> - cancel_timer(StateData#state.timer); - true -> - ok - end, - Timer = if + cancel_timer(StateData#state.timer), + Timer = if StateData#state.pause > 0 -> erlang:start_timer( StateData#state.pause*1000, self(), []); @@ -476,9 +449,9 @@ handle_sync_event({http_get, Rid, Wait, Hold}, From, StateName, StateData) -> key=StateData#state.key, in=StateData#state.input, out=StateData#state.output - } | - [El || El <- StateData#state.req_list, - El#hbr.rid /= Rid ] + } | + [El || El <- StateData#state.req_list, + El#hbr.rid /= Rid ] ], {reply, Reply, StateName, StateData#state{ input = "", @@ -504,24 +477,19 @@ code_change(_OldVsn, StateName, StateData, _Extra) -> %% Func: handle_info/3 %% Returns: {next_state, NextStateName, NextStateData} | %% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} +%% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- handle_info({timeout, Timer, _}, _StateName, #state{timer = Timer} = StateData) -> - ?DEBUG("ding dong", []), + ?DEBUG("Session timeout. Closing the HTTP bind Session.", []), {stop, normal, StateData}; handle_info({timeout, WaitTimer, _}, StateName, #state{wait_timer = WaitTimer} = StateData) -> if StateData#state.http_receiver /= undefined -> - if - StateData#state.timer /= undefined -> - cancel_timer(StateData#state.timer); - true -> - ok - end, - Timer = if + cancel_timer(StateData#state.timer), + Timer = if StateData#state.pause > 0 -> erlang:start_timer( StateData#state.pause*1000, self(), []); @@ -580,7 +548,7 @@ process_http_put({http_put, Rid, Attrs, Payload, Hold, StreamTo, IP}, NewKey = xml:get_attr_s("newkey", Attrs), KeyAllow = case RidAllow of - repeat -> + repeat -> true; false -> false; @@ -602,14 +570,14 @@ process_http_put({http_put, Rid, Attrs, Payload, Hold, StreamTo, IP}, end, {TMegSec, TSec, TMSec} = now(), TNow = (TMegSec * 1000000 + TSec) * 1000000 + TMSec, - LastPoll = if + LastPoll = if Payload == "" -> TNow; true -> 0 end, if - (Payload == "") and + (Payload == "") and (Hold == 0) and (TNow - StateData#state.last_poll < ?MIN_POLLING) -> Reply = {error, polling_too_frequently}, @@ -622,7 +590,7 @@ process_http_put({http_put, Rid, Attrs, Payload, Hold, StreamTo, IP}, repeat -> ?DEBUG("REPEATING ~p", [Rid]), Reply = case [El#hbr.out || - El <- StateData#state.req_list, + El <- StateData#state.req_list, El#hbr.rid == Rid] of [] -> {error, not_exists}; @@ -631,10 +599,10 @@ process_http_put({http_put, Rid, Attrs, Payload, Hold, StreamTo, IP}, [Out | _XS] -> {repeat, Out} end, - {reply, Reply, StateName, + {reply, Reply, StateName, StateData#state{input = "cancel", last_poll = LastPoll}}; {true, Pause} -> - SaveKey = if + SaveKey = if NewKey == "" -> Key; true -> @@ -647,20 +615,15 @@ process_http_put({http_put, Rid, Attrs, Payload, Hold, StreamTo, IP}, key=StateData#state.key, in=StateData#state.input, out=StateData#state.output - } | - [El || El <- StateData#state.req_list, - El#hbr.rid < Rid, + } | + [El || El <- StateData#state.req_list, + El#hbr.rid < Rid, El#hbr.rid > (Rid - 1 - Hold)] ], ?DEBUG("reqlist: ~p", [ReqList]), - + %% setup next timer - if - StateData#state.timer /= undefined -> - cancel_timer(StateData#state.timer); - true -> - ok - end, + cancel_timer(StateData#state.timer), Timer = if Pause > 0 -> erlang:start_timer( @@ -673,7 +636,7 @@ process_http_put({http_put, Rid, Attrs, Payload, Hold, StreamTo, IP}, false -> Input = Payload ++ [StateData#state.input], Reply = ok, - process_buffered_request(Reply, StateName, + process_buffered_request(Reply, StateName, StateData#state{input = Input, rid = Rid, key = SaveKey, @@ -685,18 +648,18 @@ process_http_put({http_put, Rid, Attrs, Payload, Hold, StreamTo, IP}, ip = IP }); {Receiver, _Tag} -> - SendPacket = + SendPacket = case StreamTo of {To, ""} -> [""] + "xmlns:stream='"++?NS_STREAM++"'>"] ++ Payload; {To, Version} -> [""] + "xmlns:stream='"++?NS_STREAM++"'>"] ++ Payload; _ -> Payload @@ -706,7 +669,7 @@ process_http_put({http_put, Rid, Attrs, Payload, Hold, StreamTo, IP}, Receiver ! {tcp, StateData#state.socket, list_to_binary(SendPacket)}, Reply = ok, - process_buffered_request(Reply, StateName, + process_buffered_request(Reply, StateName, StateData#state{waiting_input = false, last_receiver = Receiver, input = "", @@ -743,13 +706,13 @@ process_buffered_request(Reply, StateName, StateData) -> handle_http_put(Sid, Rid, Attrs, Payload, StreamStart, IP) -> case http_put(Sid, Rid, Attrs, Payload, StreamStart, IP) of {error, not_exists} -> - ?DEBUG("no session associated with sid: ~p", [Sid]), + ?ERROR_MSG("no session associated with sid: ~p", [Sid]), {404, ?HEADER, ""}; {{error, Reason}, Sess} -> + ?ERROR_MSG("Error on HTTP put. Reason: ~p", [Reason]), handle_http_put_error(Reason, Sess); {{repeat, OutPacket}, Sess} -> - ?DEBUG("http_put said 'repeat!' ...~nOutPacket: ~p", - [OutPacket]), + ?DEBUG("http_put said 'repeat!' ...~nOutPacket: ~p", [OutPacket]), send_outpacket(Sess, OutPacket); {ok, Sess} -> prepare_response(Sess, Rid, Attrs, StreamStart) @@ -761,7 +724,7 @@ http_put(Sid, Rid, Attrs, Payload, StreamStart, IP) -> [] -> {error, not_exists}; [#http_bind{pid = FsmRef, hold=Hold, to={To, StreamVersion}}=Sess] -> - NewStream = + NewStream = case StreamStart of true -> {To, StreamVersion}; @@ -772,26 +735,26 @@ http_put(Sid, Rid, Attrs, Payload, StreamStart, IP) -> FsmRef, {http_put, Rid, Attrs, Payload, Hold, NewStream, IP}), Sess} end. -handle_http_put_error(Reason, #http_bind{pid=FsmRef, version=Version}) +handle_http_put_error(Reason, #http_bind{pid=FsmRef, version=Version}) when Version >= 0 -> gen_fsm:sync_send_all_state_event(FsmRef,stop), case Reason of not_exists -> - {200, ?HEADER, + {200, ?HEADER, xml:element_to_string( {xmlelement, "body", [{"xmlns", ?NS_HTTP_BIND}, {"type", "terminate"}, {"condition", "item-not-found"}], []})}; bad_key -> - {200, ?HEADER, + {200, ?HEADER, xml:element_to_string( {xmlelement, "body", [{"xmlns", ?NS_HTTP_BIND}, {"type", "terminate"}, {"condition", "item-not-found"}], []})}; polling_too_frequently -> - {200, ?HEADER, + {200, ?HEADER, xml:element_to_string( {xmlelement, "body", [{"xmlns", ?NS_HTTP_BIND}, @@ -800,19 +763,21 @@ handle_http_put_error(Reason, #http_bind{pid=FsmRef, version=Version}) end; handle_http_put_error(Reason, #http_bind{pid=FsmRef}) -> gen_fsm:sync_send_all_state_event(FsmRef,stop), - case Reason of + case Reason of not_exists -> %% bad rid + ?ERROR_MSG("Closing HTTP bind session (Bad rid).", []), {404, ?HEADER, ""}; bad_key -> + ?ERROR_MSG("Closing HTTP bind session (Bad key).", []), {404, ?HEADER, ""}; polling_too_frequently -> - {403, ?HEADER, ""} + ?ERROR_MSG("Closing HTTP bind session (User polling too frequently).", []), + {403, ?HEADER, ""} end. - -prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold, to=To}=Sess, +prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold, to=To}=Sess, Rid, _, StreamStart) -> - receive after 100 -> ok end, + receive after 100 -> ok end, %% TODO: Why is this needed. Argh. Bad programming practice. case catch http_get(Sess, Rid) of {ok, cancel} -> %% actually it would be better if we could completely @@ -829,7 +794,7 @@ prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold, to=To}=Sess, false -> send_outpacket(Sess, OutPacket); true -> - OutEls = + OutEls = case xml_stream:parse_element( OutPacket++"") of El when element(1, El) == xmlelement -> @@ -842,14 +807,14 @@ prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold, to=To}=Sess, case Els of [] -> []; - [{xmlelement, "stream:features", - StreamAttribs, StreamEls} + [{xmlelement, "stream:features", + StreamAttribs, StreamEls} | StreamTail] -> - [{xmlelement, "stream:features", + [{xmlelement, "stream:features", [{"xmlns:stream", ?NS_STREAM} - ] - ++ StreamAttribs, + ] + ++ StreamAttribs, StreamEls }] ++ StreamTail; Xml -> @@ -868,11 +833,11 @@ prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold, to=To}=Sess, "condition='host-unknown' " "xmlns='"++?NS_HTTP_BIND++"'/>"}; true -> - BOSH_attribs = + BOSH_attribs = [{"authid", AuthID}, {"xmlns:xmpp", ?NS_BOSH}, {"xmlns:stream", ?NS_STREAM}] ++ - case OutEls of + case OutEls of [] -> []; _ -> @@ -887,12 +852,12 @@ prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold, to=To}=Sess, {"sid", Sid}, {"wait", integer_to_list(Wait)}, {"requests", integer_to_list(Hold+1)}, - {"inactivity", + {"inactivity", integer_to_list( trunc(MaxInactivity/1000))}, {"maxpause", integer_to_list(?MAX_PAUSE)}, - {"polling", + {"polling", integer_to_list( trunc(?MIN_POLLING/1000000))}, {"ver", ?BOSH_VERSION}, @@ -919,9 +884,9 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> gen_fsm:sync_send_all_state_event(FsmRef,stop), {200, ?HEADER, ""}; _ -> - case xml_stream:parse_element("" + case xml_stream:parse_element("" ++ OutPacket - ++ "") + ++ "") of El when element(1, El) == xmlelement -> {xmlelement, _, _, OEls} = El, @@ -949,18 +914,18 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> case SEls of [] -> []; - [{xmlelement, - "stream:features", - StreamAttribs, StreamEls} | + [{xmlelement, + "stream:features", + StreamAttribs, StreamEls} | StreamTail] -> - TypedTail = + TypedTail = [check_default_xmlns(OEl) || OEl <- StreamTail], - [{xmlelement, - "stream:features", + [{xmlelement, + "stream:features", [{"xmlns:stream", - ?NS_STREAM}] ++ - StreamAttribs, StreamEls}] ++ + ?NS_STREAM}] ++ + StreamAttribs, StreamEls}] ++ TypedTail; Xml -> Xml @@ -971,7 +936,7 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> end, if StreamError -> - StreamErrCond = + StreamErrCond = case xml_stream:parse_element( "" ++ OutPacket) of El when element(1, El) == xmlelement -> @@ -1013,14 +978,13 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> end. parse_request(Data) -> - ?DEBUG("--- incoming data --- ~n~s~n --- END --- ", - [Data]), + ?DEBUG("--- incoming data --- ~n~s~n --- END --- ", [Data]), case xml_stream:parse_element(Data) of El when element(1, El) == xmlelement -> {xmlelement, Name, Attrs, Els} = El, Xmlns = xml:get_attr_s("xmlns",Attrs), - if - Name /= "body" -> + if + Name /= "body" -> {error, bad_request}; Xmlns /= ?NS_HTTP_BIND -> {error, bad_request}; @@ -1029,29 +993,32 @@ parse_request(Data) -> {'EXIT', _} -> {error, bad_request}; Rid -> - FixedEls = + %% I guess this is to remove XMLCDATA: + FixedEls = lists:filter( - fun(I) -> - case I of + fun(I) -> + case I of {xmlelement, _, _, _} -> true; _ -> false end end, Els), - lists:map( - fun(E) -> - EXmlns = xml:get_tag_attr_s("xmlns",E), - if - EXmlns == ?NS_CLIENT -> - remove_tag_attr("xmlns",E); - true -> - ok - end - end, FixedEls), - Payload = [xml:element_to_string(E) || - E <- FixedEls], + %% MR: I commented this code, because it is not used. +%% lists:map( +%% fun(E) -> +%% EXmlns = xml:get_tag_attr_s("xmlns",E), +%% if +%% EXmlns == ?NS_CLIENT -> +%% remove_tag_attr("xmlns",E); +%% true -> +%% ok +%% end +%% end, FixedEls), + Payload = [xml:element_to_string(E) || E <- FixedEls], Sid = xml:get_attr_s("sid",Attrs), + %% MR: I do not think we need to extract + %% Sid. We should have it somewhere else: {ok, {Sid, Rid, Attrs, Payload}} end end; @@ -1059,6 +1026,9 @@ parse_request(Data) -> {error, bad_request} end. +%% Cancel timer and empty message queue. +cancel_timer(undefined) -> + ok; cancel_timer(Timer) -> erlang:cancel_timer(Timer), receive @@ -1068,6 +1038,7 @@ cancel_timer(Timer) -> ok end. +%% TODO: Use tail recursion and list reverse ? elements_to_string([]) -> []; elements_to_string([El | Els]) -> @@ -1085,24 +1056,20 @@ get_max_inactivity({Host, _}, Default) -> get_max_inactivity(_, Default) -> Default. +remove_tag_attr(Attr, {xmlelement, Name, Attrs, Els}) -> + Attrs1 = lists:keydelete(Attr, 1, Attrs), + {xmlelement, Name, Attrs1, Els}; remove_tag_attr(Attr, El) -> - case El of - {xmlelement, Name, Attrs, Els} -> - Attrs1 = lists:keydelete(Attr, 1, Attrs), - {xmlelement, Name, Attrs1, Els}; - _ -> - El - end. + El. check_default_xmlns({xmlelement, Name, Attrs, Els} = El) -> - EXmlns = xml:get_tag_attr_s("xmlns", El), - if - EXmlns == "" -> - {xmlelement, Name, [{"xmlns", ?NS_CLIENT} | Attrs], Els}; - true -> - El + case xml:get_tag_attr_s("xmlns", El) of + "" -> {xmlelement, Name, [{"xmlns", ?NS_CLIENT} | Attrs], Els}; + _ -> El end. +%% Check that mod_http_bind has been defined in config file. +%% Print a warning in log file if this is not the case. check_bind_module(XmppDomain) -> case gen_mod:is_loaded(XmppDomain, mod_http_bind) of true -> ok;