diff --git a/ChangeLog b/ChangeLog index 3debdf201..863cfc566 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,22 @@ +2003-02-21 Alexey Shchepin + + * src/mod_offline.erl: Now possible to unload this module + * src/ejabberd_sm.erl: Added checks to work correctly when + mod_offline not loaded + * src/ejabberd_c2s.erl: Likewise + + * src/mod_register.erl: Added support for users removal + + * src/ejabberd_auth.erl: Added function to remove user only if + specified password correct + + * src/mod_irc/mod_irc_connection.erl: Fixed bug with changing + availability status, added processing of "QUIT" message + 2003-02-20 Alexey Shchepin * src/mod_roster.erl: Fixed bug with handling of roster set - stanzas that contains CDATA + stanzas which contains CDATA * src/mod_irc/mod_irc_connection.erl (handle_info/3): Fixed parsing of string that have "\n" line separators (not "\r\n") diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index b977103c4..49d293def 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -10,9 +10,6 @@ -author('alexey@sevcom.net'). -vsn('$Revision$ '). -%%-compile(export_all). -%%-export([Function/Arity, ...]). - -behaviour(gen_server). %% External exports @@ -24,7 +21,8 @@ dirty_get_registered_users/0, get_password_s/1, is_user_exists/1, - remove_user/1]). + remove_user/1, + remove_user/2]). %% gen_server callbacks -export([init/1, @@ -200,3 +198,24 @@ remove_user(User) -> mnesia:delete({passwd, LUser}) end, mnesia:transaction(F). + +remove_user(User, Password) -> + LUser = jlib:tolower(User), + F = fun() -> + case mnesia:read({passwd, LUser}) of + [#passwd{password = Password}] -> + mnesia:delete({passwd, LUser}), + ok; + [_] -> + not_allowed; + _ -> + not_exists + end + end, + case mnesia:transaction(F) of + {atomic, Res} -> + Res; + _ -> + bad_request + end. + diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index f5b722e32..abbcfded5 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -514,8 +514,8 @@ presence_update(From, Packet, StateData) -> FromUnavail -> % TODO: watching ourself - mod_offline:resend_offline_messages( - StateData#state.user), + catch mod_offline:resend_offline_messages( + StateData#state.user), presence_broadcast_first( From, StateData#state{pres_last = Packet, pres_invis = false diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 0f5efe839..e715e4cf1 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -243,8 +243,8 @@ do_route(From, To, Packet) -> true -> if Subsc -> - mod_offline:store_packet( - From, To, Packet); + catch mod_offline:store_packet( + From, To, Packet); true -> ok end @@ -298,9 +298,18 @@ route_message(From, To, Packet) -> {'EXIT', _} -> case ejabberd_auth:is_user_exists(User) of true -> - mod_offline:store_packet(From, To, Packet); + case catch mod_offline:store_packet(From, To, Packet) of + {'EXIT', _} -> + Err = jlib:make_error_reply( + Packet, "503", "Service Unavailable"), + ejabberd_router:route(To, From, Err); + _ -> + ok + end; _ -> - ?DEBUG("packet droped~n", []) + Err = jlib:make_error_reply( + Packet, "404", "Not Found"), + ejabberd_router:route(To, From, Err) end; {_, R} -> ejabberd_sm ! {route, diff --git a/src/mod_irc/mod_irc_connection.erl b/src/mod_irc/mod_irc_connection.erl index 4b1ff0090..8e9c88d27 100644 --- a/src/mod_irc/mod_irc_connection.erl +++ b/src/mod_irc/mod_irc_connection.erl @@ -190,14 +190,20 @@ handle_info({route_chan, Channel, Resource, "unsubscribe" -> StateData; "unsubscribed" -> StateData; _ -> + Nick = case Resource of + "" -> + StateData#state.nick; + _ -> + Resource + end, S1 = ?SEND(io_lib:format("NICK ~s\r\n" "JOIN #~s\r\n", - [Resource, Channel])), + [Nick, Channel])), case dict:is_key(Channel, S1#state.channels) of true -> - S1#state{nick = Resource}; + S1#state{nick = Nick}; _ -> - S1#state{nick = Resource, + S1#state{nick = Nick, channels = dict:store(Channel, ?SETS:new(), S1#state.channels)} @@ -311,6 +317,8 @@ handle_info({ircstring, [$: | String]}, StateName, StateData) -> StateData; [From, "PART", [$# | Chan] | _] -> process_part(StateData, Chan, From, String); + [From, "QUIT" | _] -> + process_quit(StateData, From, String); [From, "JOIN", Chan | _] -> process_join(StateData, Chan, From, String); [From, "MODE", [$# | Chan], "+o", Nick | _] -> @@ -606,6 +614,32 @@ process_part(StateData, Chan, From, String) -> end. +process_quit(StateData, From, String) -> + [FromUser | _] = string:tokens(From, "!"), + %Msg = lists:last(string:tokens(String, ":")), + NewChans = + dict:map( + fun(Chan, Ps) -> + case ?SETS:is_member(FromUser, Ps) of + true -> + ejabberd_router:route( + {lists:concat([Chan, "%", StateData#state.server]), + StateData#state.myname, FromUser}, + StateData#state.user, + {xmlelement, "presence", [{"type", "unavailable"}], + [{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], + [{xmlelement, "item", + [{"affiliation", "member"}, + {"role", "none"}], + []}]}]}), + remove_element(FromUser, Ps); + _ -> + Ps + end + end, StateData#state.channels), + StateData. + + process_join(StateData, Channel, From, String) -> [FromUser | _] = string:tokens(From, "!"), Chan = lists:subtract(Channel, ":#"), diff --git a/src/mod_offline.erl b/src/mod_offline.erl index eab2d1ba8..e85c9488e 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -59,10 +59,11 @@ receive_all(Msgs) -> stop() -> - % TODO: maybe throw error that this module can't be removed? + exit(whereis(?PROCNAME), stop), ok. store_packet(From, To, Packet) -> + true = is_process_alive(whereis(?PROCNAME)), case check_event(From, To, Packet) of true -> {User, Server, Resource} = To, diff --git a/src/mod_register.erl b/src/mod_register.erl index 811e8f029..c585cb715 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -32,9 +32,56 @@ process_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> UTag = xml:get_subtag(SubEl, "username"), PTag = xml:get_subtag(SubEl, "password"), RTag = xml:get_subtag(SubEl, "remove"), + Server = ?MYNAME, if (UTag /= false) and (RTag /= false) -> - {iq, ID, error, XMLNS, + User = xml:get_tag_cdata(UTag), + case From of + {User, Server, _} -> + ejabberd_auth:remove_user(User), + {iq, ID, result, XMLNS, [SubEl]}; + _ -> + if + PTag /= false -> + Password = xml:get_tag_cdata(PTag), + case ejabberd_auth:remove_user(User, + Password) of + ok -> + {iq, ID, result, XMLNS, [SubEl]}; + not_allowed -> + {iq, ID, error, XMLNS, + [SubEl, {xmlelement, + "error", + [{"code", "405"}], + [{xmlcdata, + "Not Allowed"}]}]}; + not_exists -> + {iq, ID, error, XMLNS, + [SubEl, {xmlelement, + "error", + [{"code", "404"}], + [{xmlcdata, + "Not Found"}]}]}; + _ -> + {iq, ID, error, XMLNS, + [SubEl, + {xmlelement, + "error", + [{"code", "500"}], + [{xmlcdata, + "Internal Server Error"}]}]} + end; + true -> + {iq, ID, error, XMLNS, + [SubEl, + {xmlelement, + "error", + [{"code", "400"}], + [{xmlcdata, + "Bad Request"}]}]} + end + end; + {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error", [{"code", "501"}], @@ -42,7 +89,6 @@ process_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> (UTag /= false) and (PTag /= false) -> User = xml:get_tag_cdata(UTag), Password = xml:get_tag_cdata(PTag), - Server = ?MYNAME, case From of {User, Server, _} -> ejabberd_auth:set_password(User, Password),