aboutsummaryrefslogtreecommitdiff
path: root/src/mod_muc/mod_muc.erl
diff options
context:
space:
mode:
authorBadlop <badlop@process-one.net>2008-12-23 13:04:42 +0000
committerBadlop <badlop@process-one.net>2008-12-23 13:04:42 +0000
commit35b1e2885e0448a3c96bc06941e27f66bc49497e (patch)
treee0b8ce40e2fc6a0d681cc873927939a875563df6 /src/mod_muc/mod_muc.erl
parenttypo fix (diff)
* src/jlib.erl: Implementation of XEP-0059 Result Set
Management (thanks to Eric Cestari)(EJAB-807) * src/jlib.hrl: Likewise * src/mod_muc/mod_muc.erl: Likewise SVN Revision: 1750
Diffstat (limited to 'src/mod_muc/mod_muc.erl')
-rw-r--r--src/mod_muc/mod_muc.erl73
1 files changed, 70 insertions, 3 deletions
diff --git a/src/mod_muc/mod_muc.erl b/src/mod_muc/mod_muc.erl
index 880540bef..022610a27 100644
--- a/src/mod_muc/mod_muc.erl
+++ b/src/mod_muc/mod_muc.erl
@@ -124,10 +124,11 @@ forget_room(Host, Name) ->
mnesia:transaction(F).
process_iq_disco_items(Host, From, To, #iq{lang = Lang} = IQ) ->
+ Rsm = jlib:rsm_decode(IQ),
Res = IQ#iq{type = result,
sub_el = [{xmlelement, "query",
[{"xmlns", ?NS_DISCO_ITEMS}],
- iq_disco_items(Host, From, Lang)}]},
+ iq_disco_items(Host, From, Lang, Rsm)}]},
ejabberd_router:route(To,
From,
jlib:iq_to_xml(Res)).
@@ -512,10 +513,11 @@ iq_disco_info(Lang) ->
{xmlelement, "feature", [{"var", ?NS_DISCO_ITEMS}], []},
{xmlelement, "feature", [{"var", ?NS_MUC}], []},
{xmlelement, "feature", [{"var", ?NS_REGISTER}], []},
+ {xmlelement, "feature", [{"var", ?NS_RSM}], []},
{xmlelement, "feature", [{"var", ?NS_VCARD}], []}].
-iq_disco_items(Host, From, Lang) ->
+iq_disco_items(Host, From, Lang, none) ->
lists:zf(fun(#muc_online_room{name_host = {Name, _Host}, pid = Pid}) ->
case catch gen_fsm:sync_send_all_state_event(
Pid, {get_disco_item, From, Lang}, 100) of
@@ -528,7 +530,72 @@ iq_disco_items(Host, From, Lang) ->
_ ->
false
end
- end, get_vh_rooms(Host)).
+ end, get_vh_rooms(Host));
+
+iq_disco_items(Host, From, Lang, Rsm) ->
+ {Rooms, RsmO} = get_vh_rooms(Host, Rsm),
+ RsmOut = jlib:rsm_encode(RsmO),
+ lists:zf(fun(#muc_online_room{name_host = {Name, _Host}, pid = Pid}) ->
+ case catch gen_fsm:sync_send_all_state_event(
+ Pid, {get_disco_item, From, Lang}, 100) of
+ {item, Desc} ->
+ flush(),
+ {true,
+ {xmlelement, "item",
+ [{"jid", jlib:jid_to_string({Name, Host, ""})},
+ {"name", Desc}], []}};
+ _ ->
+ false
+ end
+ end, Rooms) ++ RsmOut.
+
+get_vh_rooms(Host, #rsm_in{max=M, direction=Direction, id=I, index=Index})->
+ AllRooms = lists:sort(get_vh_rooms(Host)),
+ Count = erlang:length(AllRooms),
+ Guard = case Direction of
+ _ when Index =/= undefined -> [{'==', {element, 2, '$1'}, Host}];
+ aft -> [{'==', {element, 2, '$1'}, Host}, {'>=',{element, 1, '$1'} ,I}];
+ before when I =/= []-> [{'==', {element, 2, '$1'}, Host}, {'=<',{element, 1, '$1'} ,I}];
+ _ -> [{'==', {element, 2, '$1'}, Host}]
+ end,
+ L = lists:sort(
+ mnesia:dirty_select(muc_online_room,
+ [{#muc_online_room{name_host = '$1', _ = '_'},
+ Guard,
+ ['$_']}])),
+ L2 = if
+ Index == undefined andalso Direction == before ->
+ lists:reverse(lists:sublist(lists:reverse(L), 1, M));
+ Index == undefined ->
+ lists:sublist(L, 1, M);
+ Index > Count orelse Index < 0 ->
+ [];
+ true ->
+ lists:sublist(L, Index+1, M)
+ end,
+ if
+ L2 == [] ->
+ {L2, #rsm_out{count=Count}};
+ true ->
+ H = hd(L2),
+ NewIndex = get_room_pos(H, AllRooms),
+ T=lists:last(L2),
+ {F, _}=H#muc_online_room.name_host,
+ {Last, _}=T#muc_online_room.name_host,
+ {L2, #rsm_out{first=F, last=Last, count=Count, index=NewIndex}}
+ end.
+
+%% @doc Return the position of desired room in the list of rooms.
+%% The room must exist in the list. The count starts in 0.
+%% @spec (Desired::muc_online_room(), Rooms::[muc_online_room()]) -> integer()
+get_room_pos(Desired, Rooms) ->
+ get_room_pos(Desired, Rooms, 0).
+get_room_pos(Desired, [HeadRoom | _], HeadPosition)
+ when (Desired#muc_online_room.name_host ==
+ HeadRoom#muc_online_room.name_host) ->
+ HeadPosition;
+get_room_pos(Desired, [_ | Rooms], HeadPosition) ->
+ get_room_pos(Desired, Rooms, HeadPosition + 1).
flush() ->
receive