diff options
author | Alexey Shchepin <alexey@process-one.net> | 2002-12-13 20:58:27 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2002-12-13 20:58:27 +0000 |
commit | 496c041b28d551be8ca7524daebdf9705d943aae (patch) | |
tree | ef866b4c0dffd18162bfe78333f3ee796f11a2b2 /src/mod_roster.erl | |
parent | *** empty log message *** (diff) |
*** empty log message ***
SVN Revision: 16
Diffstat (limited to 'src/mod_roster.erl')
-rw-r--r-- | src/mod_roster.erl | 206 |
1 files changed, 184 insertions, 22 deletions
diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 7e327a51e..a686f9ce0 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -12,36 +12,198 @@ -export([]). --export([start/0]). +-export([start/0, init/0, process_iq/3]). --record(roster, {user, jid, name, subscription, groups, xs}). +-include_lib("mnemosyne/include/mnemosyne.hrl"). +-include("ejabberd.hrl"). +-record(roster, {user, + jid, + name = "", + subscription = none, + groups = [], + xattrs = [], + xs = []}). + +-define(ME, ejabberd_mod_roster). start() -> + register(?ME, spawn(mod_roster, init, [])). + +init() -> mnesia:create_table(roster,[{disc_copies, [node()]}, {type, bag}, {attributes, record_info(fields, roster)}]), + mnesia:add_table_index(roster, jid), ejabberd_local:register_iq_handler("jabber:iq:roster", - ?MODULE, process_iq). - %spawn(mod_roster, init, []). - -%init() -> -% loop(). -% -%loop() -> -% receive -% _ -> -% loop() -% end. - - -% TODO -process_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> - case Type of - set -> - {iq, ID, error, XMLNS, []}; - get -> - {iq, ID, error, XMLNS, []} + ?MODULE, process_iq), + loop(). + +loop() -> + receive + {process_iq, From, To, {iq, ID, Type, XMLNS, SubEl}} -> + case Type of + set -> + ResIQ = process_iq_set(From, To, + {iq, ID, Type, XMLNS, SubEl}), + ejabberd_router ! {route, + To, + From, + jlib:iq_to_xml(ResIQ)}, + loop(); + get -> + ResIQ = process_iq_get(From, To, + {iq, ID, Type, XMLNS, SubEl}), + ejabberd_router ! {route, + To, + From, + jlib:iq_to_xml(ResIQ)}, + loop() + end + end. + + + +process_iq(From, To, IQ) -> + {iq, ID, Type, XMLNS, SubEl} = IQ, + {_, Server, _} = From, + case ?MYNAME of + Server -> + ?ME ! {process_iq, From, To, IQ}, + ignore; + _ -> + {iq, ID, error, XMLNS, + [SubEl, jlib:make_error_element("404", "Not Found")]} end. +process_iq_get(From, To, {iq, ID, Type, XMLNS, SubEl}) -> + {User, _, _} = From, + F = fun() -> + mnesia:read({roster, User}) + end, + case mnesia:transaction(F) of + {atomic, Items} -> + XItems = lists:map(fun item_to_xml/1, Items), + {iq, ID, result, XMLNS, XItems}; + _ -> + {iq, ID, error, XMLNS, + [SubEl, jlib:make_error_element("500", + "Internal Server Error")]} + end. + +item_to_xml(Item) -> + Attrs1 = [{"jid", jlib:jid_to_string(Item#roster.jid)}], + Attrs2 = case Item#roster.name of + "" -> + Attrs1; + Name -> + [{"name", Name} | Attrs1] + end, + Attrs3 = case Item#roster.subscription of + none -> + [{"subscription", "none"} | Attrs2]; + _ -> + % TODO + Attrs2 + end, + Attrs = Attrs3 ++ Item#roster.xattrs, + SubEls1 = lists:map(fun(G) -> + {xmlelement, "group", [], [{xmlcdata, G}]} + end, Item#roster.groups), + SubEls = SubEls1 ++ Item#roster.xs, + {xmlelement, "item", Attrs, SubEls}. + + +process_iq_set(From, To, {iq, ID, Type, XMLNS, SubEl}) -> + {User, _, _} = From, + {xmlelement, Name, Attrs, Els} = SubEl, + lists:foreach(fun(El) -> process_item_set(User, To, El) end, Els), + {iq, ID, result, XMLNS, []}. + +process_item_set(User, To, XItem) -> + {xmlelement, Name, Attrs, Els} = XItem, + % TODO: load existing item + JID = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)), + case JID of + error -> + ok; + _ -> + F = fun() -> + Res = mnemosyne:eval(query [X || X <- table(roster), + X.user = User, + X.jid = JID] + end), + Item = case Res of + [] -> + #roster{user = User, + jid = JID, + groups = [], + xattrs = [], + xs = []}; + [I] -> + mnesia:delete_object(I), + I + end, + Item1 = process_item_attrs(Item, Attrs), + Item2 = process_item_els(Item1, Els), + mnesia:write(Item2), + Item2 + end, + case mnesia:transaction(F) of + {atomic, Item} -> + io:format("ROSTER: push for user ~p: ~p~n", [User, Item]), + ok; + _ -> + ok + end + end. + +process_item_attrs(Item, [{Attr, Val} | Attrs]) -> + case Attr of + "jid" -> + case jlib:string_to_jid(Val) of + error -> + process_item_attrs(Item, [Attrs]); + JID -> + process_item_attrs(Item#roster{jid = JID}, [Attrs]) + end; + "name" -> + process_item_attrs(Item#roster{name = Val}, [Attrs]); + "subscription" -> + case Val of + "remove" -> + process_item_attrs(Item#roster{subscription = remove}, + [Attrs]); + _ -> + process_item_attrs(Item, [Attrs]) + end; + "ask" -> + process_item_attrs(Item, [Attrs]); + _ -> + XAttrs = Item#roster.xattrs, + process_item_attrs(Item#roster{xattrs = [{Attr, Val} | XAttrs]}, + [Attrs]) + end; +process_item_attrs(Item, []) -> + Item. + +% {user, jid, name, subscription, groups, xattrs, xs} +process_item_els(Item, [{xmlelement, Name, Attrs, SEls} | Els]) -> + case Name of + "group" -> + Groups = [xml:get_cdata(SEls) | Item#roster.groups], + process_item_els(Item#roster{groups = Groups}, Els); + _ -> + case xml:get_attr_s("xmlns", Attrs) of + "" -> + process_item_els(Item, Els); + _ -> + XEls = [{xmlelement, Name, Attrs, SEls} | Item#roster.xs], + process_item_els(Item#roster{xs = XEls}, Els) + end + end; +process_item_els(Item, [{xmlcdata, _} | Els]) -> + process_item_els(Item, Els); +process_item_els(Item, []) -> + Item. |