+2003-05-29 Alexey Shchepin <alexey@sevcom.net>
+
+ * src/ejabberd_service.erl: Proper handling of bad XML
+
+ * src/mod_muc/mod_muc_room.erl: Append number of participants in
+ disco replies if requester allowed to see participant list
+
+ * src/mod_muc/mod_muc.erl (iq_disco_items): Pass requester JID to
+ room process
+
+ * src/mod_irc/mod_irc_connection.erl: Exit on receiving of
+ presence or message error
+
+ * src/mod_irc/mod_irc_connection.erl (handle_info): Return
+ "feature not implemented" on iq request with unknown namespace
+
2003-05-18 Alexey Shchepin <alexey@sevcom.net>
* src/mod_muc/mod_muc.erl: Now body of message from admin to MUC
backup management
S2S:
- * timeouts
-
* rewrite S2S key validation
more correctly work with SRV DNS records (priority, weight, etc...)
-SSL
-JEP-62,63 (?)
+TLS
+Privacy rules
make roster set to work in one transaction
add traffic shapers to c2s connection before authentification
add traffic shapers to s2s connections
more traffic shapers
SNMP
+PubSub
+MUC: remove empty non-persistent conferences after timeout
+MUC: remove a lot of debugging output
+IRC: disconnect on receiving of error message or presence
"</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)).
+
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
{stop, normal, StateData}
end;
+wait_for_stream({xmlstreamerror, _}, StateData) ->
+ Header = io_lib:format(?STREAM_HEADER,
+ ["none", ?MYNAME]),
+ send_text(StateData#state.socket,
+ Header ++ ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ {stop, normal, StateData};
+
wait_for_stream(closed, StateData) ->
{stop, normal, StateData}.
wait_for_handshake({xmlstreamend, Name}, StateData) ->
{stop, normal, StateData};
+wait_for_handshake({xmlstreamerror, _}, StateData) ->
+ send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ {stop, normal, StateData};
+
wait_for_handshake(closed, StateData) ->
{stop, normal, StateData}.
% TODO
{stop, normal, StateData};
+stream_established({xmlstreamerror, _}, StateData) ->
+ send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ {stop, normal, StateData};
+
stream_established(closed, StateData) ->
% TODO
{stop, normal, StateData}.
"subscribed" -> StateData;
"unsubscribe" -> StateData;
"unsubscribed" -> StateData;
+ "error" -> stop;
_ ->
Nick = case Resource of
"" ->
S1#state.channels)}
end
end,
- case length(dict:fetch_keys(NewStateData#state.channels)) of
- 0 ->
- {stop, normal, NewStateData};
- _ ->
- {next_state, StateName, NewStateData}
+ if
+ NewStateData == stop ->
+ {stop, normal, StateData};
+ true ->
+ case length(dict:fetch_keys(NewStateData#state.channels)) of
+ 0 ->
+ {stop, normal, NewStateData};
+ _ ->
+ {next_state, StateName, NewStateData}
+ end
end;
handle_info({route_chan, Channel, Resource,
[Resource, S])
end, Strings)),
?SEND(Res);
+ "error" ->
+ stop;
_ ->
StateData
end,
- {next_state, StateName, NewStateData};
+ if
+ NewStateData == stop ->
+ {stop, normal, StateData};
+ true ->
+ {next_state, StateName, NewStateData}
+ end;
handle_info({route_chan, Channel, Resource,
ID, XMLNS, Type, SubEl);
_ ->
Err = jlib:make_error_reply(
- El, ?ERR_SERVICE_UNAVAILABLE),
+ El, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(To, From, Err)
end,
{next_state, StateName, StateData};
[Nick, S])
end, Strings)),
?SEND(Res);
+ "error" ->
+ stop;
_ ->
StateData
end,
- {next_state, StateName, NewStateData};
+ if
+ NewStateData == stop ->
+ {stop, normal, StateData};
+ true ->
+ {next_state, StateName, NewStateData}
+ end;
handle_info({route_nick, Nick, Packet}, StateName, StateData) ->
{next_state, StateName, StateData};
iq_disco_items(Host, From) ->
lists:zf(fun(#muc_online_room{name = Name, pid = Pid}) ->
case catch gen_fsm:sync_send_all_state_event(
- Pid, get_disco_item, 100) of
+ Pid, {get_disco_item, From}, 100) of
{item, Desc} ->
{true,
{xmlelement, "item",
%% {stop, Reason, NewStateData} |
%% {stop, Reason, Reply, NewStateData}
%%----------------------------------------------------------------------
-handle_sync_event(get_disco_item, From, StateName, StateData) ->
+handle_sync_event({get_disco_item, JID}, From, StateName, StateData) ->
+ FAffiliation = get_affiliation(JID, StateData),
+ FRole = get_role(JID, StateData),
+ Tail =
+ case ((StateData#state.config)#config.public_list == true) orelse
+ (FRole /= none) orelse
+ (FAffiliation == admin) orelse
+ (FAffiliation == owner) of
+ true ->
+ Len = length(?DICT:to_list(StateData#state.users)),
+ " (" ++ integer_to_list(Len) ++ ")";
+ _ ->
+ ""
+ end,
Reply = case (StateData#state.config)#config.public of
true ->
- {item, get_title(StateData)};
+ {item, get_title(StateData) ++ Tail};
_ ->
false
end,