summaryrefslogtreecommitdiff
path: root/src/mod_roster.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_roster.erl')
-rw-r--r--src/mod_roster.erl197
1 files changed, 169 insertions, 28 deletions
diff --git a/src/mod_roster.erl b/src/mod_roster.erl
index 197dc29e..6c23a0f1 100644
--- a/src/mod_roster.erl
+++ b/src/mod_roster.erl
@@ -15,15 +15,18 @@
-export([start/0, init/0,
process_iq/3,
get_subscription_lists/1,
- in_subscription/3]).
+ in_subscription/3,
+ out_subscription/3]).
-include_lib("mnemosyne/include/mnemosyne.hrl").
-include("ejabberd.hrl").
--record(roster, {user,
+-record(roster, {uj,
+ user,
jid,
name = "",
subscription = none,
+ ask = none,
groups = [],
xattrs = [],
xs = []}).
@@ -35,9 +38,8 @@ start() ->
init() ->
mnesia:create_table(roster,[{disc_copies, [node()]},
- {type, bag},
{attributes, record_info(fields, roster)}]),
- mnesia:add_table_index(roster, jid),
+ mnesia:add_table_index(roster, user),
ejabberd_local:register_iq_handler("jabber:iq:roster",
?MODULE, process_iq),
loop().
@@ -83,7 +85,7 @@ process_iq_get(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{User, _, _} = From,
LUser = jlib:tolower(User),
F = fun() ->
- mnesia:read({roster, LUser})
+ mnesia:index_read(roster, LUser, #roster.user)
end,
case mnesia:transaction(F) of
{atomic, Items} ->
@@ -108,15 +110,24 @@ item_to_xml(Item) ->
Attrs3 = case Item#roster.subscription of
none ->
[{"subscription", "none"} | Attrs2];
+ from ->
+ [{"subscription", "from"} | Attrs2];
+ to ->
+ [{"subscription", "to"} | Attrs2];
both ->
[{"subscription", "both"} | Attrs2];
remove ->
- [{"subscription", "remove"} | Attrs2];
- _ ->
- % TODO
- Attrs2
+ [{"subscription", "remove"} | Attrs2]
end,
- Attrs = Attrs3 ++ Item#roster.xattrs,
+ Attrs4 = case Item#roster.ask of
+ none ->
+ Attrs3;
+ subscribe ->
+ [{"ask", "subscribe"} | Attrs3];
+ unsubscribe ->
+ [{"ask", "unsubscribe"} | Attrs3]
+ end,
+ Attrs = Attrs4 ++ Item#roster.xattrs,
SubEls1 = lists:map(fun(G) ->
{xmlelement, "group", [], [{xmlcdata, G}]}
end, Item#roster.groups),
@@ -139,21 +150,18 @@ process_item_set(User, To, XItem) ->
error ->
ok;
_ ->
+ LJID = jlib:jid_tolower(JID),
F = fun() ->
- Res = mnemosyne:eval(query [X || X <- table(roster),
- X.user = LUser,
- X.jid = JID]
- end),
+ Res = mnesia:read({roster, {LUser, LJID}}),
Item = case Res of
[] ->
- #roster{user = LUser,
- jid = JID,
- groups = [],
- xattrs = [],
- xs = []};
+ #roster{uj = {LUser, LJID},
+ user = LUser,
+ jid = JID};
[I] ->
- mnesia:delete_object(I),
- I#roster{name = "",
+ I#roster{user = LUser,
+ jid = JID,
+ name = "",
groups = [],
xattrs = [],
xs = []}
@@ -162,7 +170,7 @@ process_item_set(User, To, XItem) ->
Item2 = process_item_els(Item1, Els),
case Item2#roster.subscription of
remove ->
- ok;
+ mnesia:delete({roster, {LUser, LJID}});
_ ->
mnesia:write(Item2)
end,
@@ -249,7 +257,7 @@ push_item(User, Resource, From, Item) ->
get_subscription_lists(User) ->
LUser = jlib:tolower(User),
F = fun() ->
- mnesia:read({roster, LUser})
+ mnesia:index_read(roster, LUser, #roster.user)
end,
case mnesia:transaction(F) of
{atomic, Items} ->
@@ -259,7 +267,8 @@ get_subscription_lists(User) ->
end.
fill_subscription_lists([I | Is], F, T) ->
- J = I#roster.jid,
+ %J = I#roster.jid,
+ J = element(2, I#roster.uj),
case I#roster.subscription of
both ->
fill_subscription_lists(Is, [J | F], [J | T]);
@@ -276,14 +285,146 @@ fill_subscription_lists([], F, T) ->
in_subscription(User, From, Type) ->
LUser = jlib:tolower(User),
+ LFrom = jlib:jid_tolower(From),
+ {FU, FS, FR} = From,
F = fun() ->
- mnesia:read({roster, LUser})
+ case mnesia:read({roster, {LUser, LFrom}}) of
+ [] ->
+ case Type of
+ subscribe ->
+ true;
+ unsubscribe ->
+ true;
+ unsubscribed ->
+ false;
+ subscribed ->
+ NewItem = #roster{uj = {LUser, LFrom},
+ user = LUser,
+ jid = From},
+ mnesia:write(NewItem),
+ true
+ end;
+ [I] ->
+ case Type of
+ subscribe ->
+ S = I#roster.subscription,
+ if
+ (S == both) or (S == from) ->
+ ejabberd_router:route(
+ {User, ?MYNAME, ""}, {FU, FS, ""},
+ {xmlelement, "presence",
+ [{"type", "subscribed"}], []}),
+ % TODO: update presence
+ false;
+ true ->
+ true
+ end;
+ unsubscribe ->
+ S = I#roster.subscription,
+ if
+ (S == none) or (S == to) ->
+ ejabberd_router:route(
+ {User, ?MYNAME, ""}, {FU, FS, ""},
+ {xmlelement, "presence",
+ [{"type", "unsubscribed"}], []}),
+ % TODO: update presence
+ false;
+ true ->
+ true
+ end;
+ _ ->
+ S = I#roster.subscription,
+ NS = case Type of
+ subscribed ->
+ case S of
+ from -> both;
+ none -> to;
+ _ -> S
+ end;
+ unsubscribed ->
+ case S of
+ both -> from;
+ to -> none;
+ _ -> S
+ end
+ end,
+ NewItem = I#roster{subscription = NS,
+ ask = none},
+ mnesia:write(NewItem),
+ {push, NewItem}
+ end
+ end
end,
case mnesia:transaction(F) of
- {atomic, Items} ->
- % TODO
+ {atomic, true} ->
+ true;
+ {atomic, false} ->
+ false;
+ {atomic, {push, Item}} ->
+ push_item(User, {"", ?MYNAME, ""}, Item),
+ true;
+ _ ->
+ false
+ end.
+
+out_subscription(User, JID, Type) ->
+ LUser = jlib:tolower(User),
+ LJID = jlib:jid_tolower(JID),
+ F = fun() ->
+ Item = case mnesia:read({roster, {LUser, LJID}}) of
+ [] ->
+ if (Type == unsubscribe) or
+ (Type == unsubscribed) ->
+ false;
+ true ->
+ #roster{uj = {LUser, LJID},
+ user = LUser,
+ jid = JID}
+ end;
+ [I] ->
+ I
+ end,
+ if Item == false ->
+ ok;
+ true ->
+ NewItem =
+ case Type of
+ subscribe ->
+ Item#roster{ask = subscribe};
+ unsubscribe ->
+ Item#roster{ask = unsubscribe};
+ subscribed ->
+ S = Item#roster.subscription,
+ NS = case S of
+ to -> both;
+ none -> from;
+ _ -> S
+ end,
+ % TODO: update presence
+ Item#roster{subscription = NS,
+ ask = none};
+ unsubscribed ->
+ S = Item#roster.subscription,
+ NS = case S of
+ both -> to;
+ from -> none;
+ _ -> S
+ end,
+ % TODO: update presence
+ Item#roster{subscription = NS,
+ ask = none}
+ end,
+ mnesia:write(NewItem),
+ {push, NewItem}
+ end
+ end,
+ case mnesia:transaction(F) of
+ {atomic, ok} ->
ok;
+ {atomic, {push, Item}} ->
+ push_item(User, {"", ?MYNAME, ""}, Item),
+ true;
_ ->
- ok
+ false
end.