]> granicus.if.org Git - ejabberd/commitdiff
Updated riak support
authorAlexey Shchepin <alexey@process-one.net>
Tue, 6 Nov 2012 15:58:08 +0000 (17:58 +0200)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Thu, 10 Jul 2014 09:15:15 +0000 (13:15 +0400)
12 files changed:
src/ejabberd_app.erl
src/ejabberd_riak.erl
src/ejabberd_riak_sup.erl
src/gen_mod.erl
src/mod_offline.erl
src/mod_offline_riak.erl [deleted file]
src/mod_private.erl
src/mod_private_riak.erl [deleted file]
src/mod_roster.erl
src/mod_roster_riak.erl [deleted file]
src/mod_vcard.erl
src/mod_vcard_riak.erl [deleted file]

index 6b0a85be893afec46c088494b2be71f3cead1aa3..379f728d61002ab2a72eaf9d6ab684cf267667bb 100644 (file)
@@ -57,6 +57,7 @@ start(normal, _Args) ->
     connect_nodes(),
     Sup = ejabberd_sup:start_link(),
     ejabberd_rdbms:start(),
+    ejabberd_riak_sup:start(),
     ejabberd_auth:start(),
     cyrsasl:start(),
     % Profiling
index ca7df6833251d9d1705b82824ac18a00199dc23c..892e8fd696a699a4ed619611848c9e68b6a8beb1 100644 (file)
@@ -28,7 +28,7 @@
 -author('alexey@process-one.net').
 
 %% External exports
--export([start_link/1,
+-export([start_link/3,
          put/4,
          put/5,
          get_object/3,
@@ -44,9 +44,9 @@
 %%%----------------------------------------------------------------------
 %%% API
 %%%----------------------------------------------------------------------
-start_link(StartInterval) ->
+start_link(Server, Port, StartInterval) ->
     {ok, Pid} = riakc_pb_socket:start_link(
-                  "127.0.0.1", 8081,
+                  Server, Port,
                   [auto_reconnect]),
     ejabberd_riak_sup:add_pid(Pid),
     {ok, Pid}.
index 38fb202bdb8b4451149fd33802bbf71c2cb99986..4ad7d4130c50bea1c6888f8b836dffafd1d38af4 100644 (file)
 -record(riak_pool, {undefined, pid}).
 
 start() ->
+    StartRiak = ejabberd_config:get_local_option(
+                  riak_server, fun(_) -> true end, false),
+    if
+        StartRiak ->
+            do_start();
+        true ->
+            ok
+    end.
+
+do_start() ->
     SupervisorName = ?MODULE,
     ChildSpec =
        {SupervisorName,
@@ -83,36 +93,26 @@ start_link() ->
 
 init([]) ->
     PoolSize =
-        case ejabberd_config:get_local_option(riak_pool_size) of
-            I when is_integer(I) ->
-                I;
-           undefined ->
-                ?DEFAULT_POOL_SIZE;
-            Other ->
-                ?ERROR_MSG("Wrong riak_pool_size definition '~p' "
-                           "default to ~p~n",
-                           [Other, ?DEFAULT_POOL_SIZE]),
-                ?DEFAULT_POOL_SIZE
-        end,
+        ejabberd_config:get_local_option(
+          riak_pool_size,
+          fun(N) when is_integer(N), N >= 1 -> N end,
+          ?DEFAULT_POOL_SIZE),
     StartInterval =
-        case ejabberd_config:get_local_option(riak_start_interval) of
-            Interval when is_integer(Interval) ->
-                Interval;
-            undefined ->
-                ?DEFAULT_RIAK_START_INTERVAL;
-            _Other2 ->
-                ?ERROR_MSG("Wrong riak_start_interval "
-                           "definition '~p', "
-                           "defaulting to ~p~n",
-                           [_Other2,
-                            ?DEFAULT_RIAK_START_INTERVAL]),
-                ?DEFAULT_RIAK_START_INTERVAL
-        end,
+        ejabberd_config:get_local_option(
+          riak_start_interval,
+          fun(N) when is_integer(N), N >= 1 -> N end,
+          ?DEFAULT_RIAK_START_INTERVAL),
+    {Server, Port} =
+        ejabberd_config:get_local_option(
+          riak_server,
+          fun({S, P}) when is_list(S), is_integer(P), P >= 1 -> {S, P} end,
+          {"127.0.0.1", 8081}),
     {ok, {{one_for_one, PoolSize*10, 1},
          lists:map(
            fun(I) ->
                    {I,
-                    {ejabberd_riak, start_link, [StartInterval*1000]},
+                    {ejabberd_riak, start_link,
+                      [Server, Port, StartInterval*1000]},
                     transient,
                      2000,
                     worker,
index 6dac8cdef585f8d2caff7de001e168e822fa3a23..00a7167469af39c28e38107e92fdbceff1357101 100644 (file)
@@ -209,22 +209,26 @@ get_opt_host(Host, Opts, Default) ->
     Val = get_opt(host, Opts, fun iolist_to_binary/1, Default),
     ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host).
 
--spec db_type(opts()) -> odbc | mnesia.
+-spec db_type(opts()) -> odbc | mnesia | riak.
 
 db_type(Opts) ->
     get_opt(db_type, Opts,
             fun(odbc) -> odbc;
                (internal) -> mnesia;
-               (mnesia) -> mnesia end,
+               (mnesia) -> mnesia;
+               (riak) -> riak
+            end,
             mnesia).
 
--spec db_type(binary(), atom()) -> odbc | mnesia.
+-spec db_type(binary(), atom()) -> odbc | mnesia | riak.
 
 db_type(Host, Module) ->
     get_module_opt(Host, Module, db_type,
                    fun(odbc) -> odbc;
                       (internal) -> mnesia;
-                      (mnesia) -> mnesia end,
+                      (mnesia) -> mnesia;
+                      (riak) -> riak
+                   end,
                    mnesia).
 
 -spec loaded_modules(binary()) -> [atom()].
index f27d358302c229ea067be89c6898be0a7efa3a19..5e2d80aa28075c96db467e6cfa08341bbeeabf63 100644 (file)
@@ -175,6 +175,56 @@ store_offline_msg(Host, {User, _Server}, Msgs, Len, MaxOfflineMsgs, odbc) ->
                             end,
                             Msgs),
           odbc_queries:add_spool(Host, Query)
+    end;
+store_offline_msg(Host, {User, _}, Msgs, Len, MaxOfflineMsgs,
+                 riak) ->
+    Count = if MaxOfflineMsgs =/= infinity ->
+                    Len + count_offline_messages(User, Host);
+               true -> 0
+            end,
+    if 
+        Count > MaxOfflineMsgs ->
+            discard_warn_sender(Msgs);
+        true ->
+            lists:foreach(
+              fun(M) ->
+                      Username = User,
+                      From = M#offline_msg.from,
+                      To = M#offline_msg.to,
+                      #xmlel{name = Name, attrs = Attrs,
+                             children = Els} =
+                          M#offline_msg.packet,
+                      Attrs2 = jlib:replace_from_to_attrs(
+                                 jlib:jid_to_string(From),
+                                 jlib:jid_to_string(To),
+                                 Attrs),
+                      Packet = #xmlel{name = Name,
+                                      attrs = Attrs2,
+                                      children =
+                                      Els ++
+                                      [jlib:timestamp_to_xml(
+                                         calendar:now_to_universal_time(
+                                           M#offline_msg.timestamp),
+                                         utc,
+                                         jlib:make_jid(<<"">>, Host, <<"">>),
+                                         <<"Offline Storage">>),
+                                       jlib:timestamp_to_xml(
+                                         calendar:now_to_universal_time(
+                                           M#offline_msg.timestamp))]},
+                      XML = xml:element_to_binary(Packet),
+                      {MegaSecs, Secs, MicroSecs} =
+                          M#offline_msg.timestamp,
+                      TS =
+                          iolist_to_binary(
+                            io_lib:format("~6..0w~6..0w.~6..0w",
+                                          [MegaSecs, Secs, MicroSecs])),
+                      ejabberd_riak:put(
+                        Host, <<"offline">>,
+                        undefined, XML,
+                        [{<<"user_bin">>, Username},
+                         {<<"timestamp_bin">>, TS}
+                        ])
+              end, Msgs)
     end.
 
 %% Function copied from ejabberd_sm.erl:
@@ -193,7 +243,8 @@ receive_all(US, Msgs, DBType) ->
       after 0 ->
                case DBType of
                  mnesia -> Msgs;
-                 odbc -> lists:reverse(Msgs)
+                 odbc -> lists:reverse(Msgs);
+                 riak -> lists:reverse(Msgs)
                end
     end.
 
@@ -421,6 +472,45 @@ pop_offline_messages(Ls, LUser, LServer, odbc) ->
                          end,
                          Rs);
       _ -> Ls
+    end;
+pop_offline_messages(Ls, LUser, LServer, riak) ->
+    Username = LUser,
+    case ejabberd_riak:get_objects_by_index(
+           LServer, <<"offline">>, <<"user_bin">>, Username) of
+        {ok, Rs} ->
+            SortedRs =
+                lists:sort(fun(X, Y) ->
+                                   MX = riak_object:get_metadata(X),
+                                   {ok, IX} = dict:find(<<"index">>, MX),
+                                   {value, TSX} = lists:keysearch(
+                                                    <<"timestamp_bin">>, 1,
+                                                    IX),
+                                   MY = riak_object:get_metadata(Y),
+                                   {ok, IY} = dict:find(<<"index">>, MY),
+                                   {value, TSY} = lists:keysearch(
+                                                    <<"timestamp_bin">>, 1,
+                                                    IY),
+                                   TSX =< TSY
+                           end, Rs),
+            Ls ++ lists:flatmap(
+                   fun(R) ->
+                            Key = riak_object:key(R),
+                            ejabberd_riak:delete(LServer, <<"offline">>, Key),
+                            XML = riak_object:get_value(R),
+                           case xml_stream:parse_element(XML) of
+                               {error, _Reason} ->
+                                   [];
+                               El ->
+                                    case offline_msg_to_route(LServer, El) of
+                                        error ->
+                                            [];
+                                        RouteMsg ->
+                                            [RouteMsg]
+                                    end
+                           end
+                   end, SortedRs);
+       _ ->
+           Ls
     end.
 
 remove_expired_messages(Server) ->
@@ -445,7 +535,8 @@ remove_expired_messages(_LServer, mnesia) ->
                             ok, offline_msg)
        end,
     mnesia:transaction(F);
-remove_expired_messages(_LServer, odbc) -> {atomic, ok}.
+remove_expired_messages(_LServer, odbc) -> {atomic, ok};
+remove_expired_messages(_LServer, riak) -> {atomic, ok}.
 
 remove_old_messages(Days, Server) ->
     LServer = jlib:nameprep(Server),
@@ -470,6 +561,8 @@ remove_old_messages(Days, _LServer, mnesia) ->
        end,
     mnesia:transaction(F);
 remove_old_messages(_Days, _LServer, odbc) ->
+    {atomic, ok};
+remove_old_messages(_Days, _LServer, riak) ->
     {atomic, ok}.
 
 remove_user(User, Server) ->
@@ -484,7 +577,19 @@ remove_user(LUser, LServer, mnesia) ->
     mnesia:transaction(F);
 remove_user(LUser, LServer, odbc) ->
     Username = ejabberd_odbc:escape(LUser),
-    odbc_queries:del_spool_msg(LServer, Username).
+    odbc_queries:del_spool_msg(LServer, Username);
+remove_user(LUser, LServer, riak) ->
+    Username = LUser,
+    case ejabberd_riak:get_keys_by_index(
+           LServer, <<"offline">>, <<"user_bin">>, Username) of
+        {ok, Keys} ->
+            lists:foreach(
+              fun(Key) ->
+                      ejabberd_riak:delete(LServer, <<"offline">>, Key)
+              end, Keys);
+        _ ->
+            ok
+    end.
 
 jid_to_binary(#jid{user = U, server = S, resource = R,
                    luser = LU, lserver = LS, lresource = LR}) ->
diff --git a/src/mod_offline_riak.erl b/src/mod_offline_riak.erl
deleted file mode 100644 (file)
index 433e583..0000000
+++ /dev/null
@@ -1,533 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File    : mod_offline_riak.erl
-%%% Author  : Alexey Shchepin <alexey@process-one.net>
-%%% Purpose : Store and manage offline messages in Riak.
-%%% Created :  4 Jan 2012 by Alexey Shchepin <alexey@process-one.net>
-%%%
-%%%
-%%% ejabberd, Copyright (C) 2002-2011   ProcessOne
-%%%
-%%% This program is free software; you can redistribute it and/or
-%%% modify it under the terms of the GNU General Public License as
-%%% published by the Free Software Foundation; either version 2 of the
-%%% License, or (at your option) any later version.
-%%%
-%%% This program is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-%%% General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License
-%%% along with this program; if not, write to the Free Software
-%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-%%% 02111-1307 USA
-%%%
-%%%----------------------------------------------------------------------
-
--module(mod_offline_riak).
--author('alexey@process-one.net').
-
--behaviour(gen_mod).
-
--export([count_offline_messages/2]).
-
--export([start/2,
-        init/2,
-        stop/1,
-        store_packet/3,
-        pop_offline_messages/3,
-        remove_user/2,
-        webadmin_page/3,
-        webadmin_user/4,
-        webadmin_user_parse_query/5,
-        count_offline_messages/3]).
-
--include("ejabberd.hrl").
--include("jlib.hrl").
--include("web/ejabberd_http.hrl").
--include("web/ejabberd_web_admin.hrl").
-
--record(offline_msg, {user, timestamp, expire, from, to, packet}).
-
--define(PROCNAME, ejabberd_offline).
--define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
-
-start(Host, Opts) ->
-    ejabberd_hooks:add(offline_message_hook, Host,
-                      ?MODULE, store_packet, 50),
-    ejabberd_hooks:add(resend_offline_messages_hook, Host,
-                      ?MODULE, pop_offline_messages, 50),
-    ejabberd_hooks:add(remove_user, Host,
-                      ?MODULE, remove_user, 50),
-    ejabberd_hooks:add(anonymous_purge_hook, Host,
-                      ?MODULE, remove_user, 50),
-    ejabberd_hooks:add(webadmin_page_host, Host,
-                      ?MODULE, webadmin_page, 50),
-    ejabberd_hooks:add(webadmin_user, Host,
-                      ?MODULE, webadmin_user, 50),
-    ejabberd_hooks:add(webadmin_user_parse_query, Host,
-                       ?MODULE, webadmin_user_parse_query, 50),
-    ejabberd_hooks:add(count_offline_messages, Host,
-                       ?MODULE, count_offline_messages, 50),
-    MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
-    register(gen_mod:get_module_proc(Host, ?PROCNAME),
-            spawn(?MODULE, init, [Host, MaxOfflineMsgs])).
-
-%% MaxOfflineMsgs is either infinity of integer > 0
-init(Host, infinity) ->
-    loop(Host, infinity);
-init(Host, MaxOfflineMsgs) 
-  when is_integer(MaxOfflineMsgs), MaxOfflineMsgs > 0 ->
-    loop(Host, MaxOfflineMsgs).
-
-loop(Host, MaxOfflineMsgs) ->
-    receive
-       #offline_msg{user = User} = Msg ->
-           Msgs = receive_all(User, [Msg]),
-           Len = length(Msgs),
-
-           %% Only count existing messages if needed:
-           Count = if MaxOfflineMsgs =/= infinity ->
-                           Len + count_offline_messages(User, Host);
-                      true -> 0
-                   end,
-           if 
-               Count > MaxOfflineMsgs ->
-                   discard_warn_sender(Msgs);
-               true ->
-                   lists:foreach(
-                      fun(M) ->
-                              Username = list_to_binary(User),
-                              From = M#offline_msg.from,
-                              To = M#offline_msg.to,
-                              {xmlelement, Name, Attrs, Els} =
-                                  M#offline_msg.packet,
-                              Attrs2 = jlib:replace_from_to_attrs(
-                                         jlib:jid_to_string(From),
-                                         jlib:jid_to_string(To),
-                                         Attrs),
-                              Packet = {xmlelement, Name, Attrs2,
-                                        Els ++
-                                        [jlib:timestamp_to_xml(
-                                           calendar:now_to_universal_time(
-                                             M#offline_msg.timestamp))]},
-                              XML =
-                                  iolist_to_binary(
-                                    xml:element_to_string(Packet)),
-                              {MegaSecs, Secs, MicroSecs} =
-                                  M#offline_msg.timestamp,
-                              TS =
-                                  iolist_to_binary(
-                                    io_lib:format("~6..0w~6..0w.~6..0w",
-                                                  [MegaSecs, Secs, MicroSecs])),
-                              ejabberd_riak:put(
-                                Host, <<"offline">>,
-                                undefined, XML,
-                                [{<<"user_bin">>, Username},
-                                 {<<"timestamp_bin">>, TS}
-                                ])
-                      end, Msgs)
-           end,
-           loop(Host, MaxOfflineMsgs);
-       _ ->
-           loop(Host, MaxOfflineMsgs)
-    end.
-
-receive_all(Username, Msgs) ->
-    receive
-       #offline_msg{user=Username} = Msg ->
-           receive_all(Username, [Msg | Msgs])
-    after 0 ->
-           lists:reverse(Msgs)
-    end.
-
-
-stop(Host) ->
-    ejabberd_hooks:delete(offline_message_hook, Host,
-                         ?MODULE, store_packet, 50),
-    ejabberd_hooks:delete(resend_offline_messages_hook, Host,
-                         ?MODULE, pop_offline_messages, 50),
-    ejabberd_hooks:delete(remove_user, Host,
-                         ?MODULE, remove_user, 50),
-    ejabberd_hooks:delete(anonymous_purge_hook, Host,
-                         ?MODULE, remove_user, 50),
-    ejabberd_hooks:delete(webadmin_page_host, Host,
-                         ?MODULE, webadmin_page, 50),
-    ejabberd_hooks:delete(webadmin_user, Host,
-                         ?MODULE, webadmin_user, 50),
-    ejabberd_hooks:delete(webadmin_user_parse_query, Host,
-                          ?MODULE, webadmin_user_parse_query, 50),
-    Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
-    exit(whereis(Proc), stop),
-    ok.
-
-store_packet(From, To, Packet) ->
-    Type = xml:get_tag_attr_s("type", Packet),
-    if
-       (Type /= "error") and (Type /= "groupchat") and
-       (Type /= "headline") ->
-           case check_event(From, To, Packet) of
-               true ->
-                   #jid{luser = LUser} = To,
-                   TimeStamp = now(),
-                   {xmlelement, _Name, _Attrs, Els} = Packet,
-                   Expire = find_x_expire(TimeStamp, Els),
-                   gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) !
-                       #offline_msg{user = LUser,
-                                    timestamp = TimeStamp,
-                                    expire = Expire,
-                                    from = From,
-                                    to = To,
-                                    packet = Packet},
-                   stop;
-               _ ->
-                   ok
-           end;
-       true ->
-           ok
-    end.
-
-check_event(From, To, Packet) ->
-    {xmlelement, Name, Attrs, Els} = Packet,
-    case find_x_event(Els) of
-       false ->
-           true;
-       El ->
-           case xml:get_subtag(El, "id") of
-               false ->
-                   case xml:get_subtag(El, "offline") of
-                       false ->
-                           true;
-                       _ ->
-                           ID = case xml:get_tag_attr_s("id", Packet) of
-                                    "" ->
-                                        {xmlelement, "id", [], []};
-                                    S ->
-                                        {xmlelement, "id", [],
-                                         [{xmlcdata, S}]}
-                                end,
-                           ejabberd_router:route(
-                             To, From, {xmlelement, Name, Attrs,
-                                        [{xmlelement, "x",
-                                          [{"xmlns", ?NS_EVENT}],
-                                          [ID,
-                                           {xmlelement, "offline", [], []}]}]
-                                       }),
-                           true
-                       end;
-               _ ->
-                   false
-           end
-    end.
-
-find_x_event([]) ->
-    false;
-find_x_event([{xmlcdata, _} | Els]) ->
-    find_x_event(Els);
-find_x_event([El | Els]) ->
-    case xml:get_tag_attr_s("xmlns", El) of
-       ?NS_EVENT ->
-           El;
-       _ ->
-           find_x_event(Els)
-    end.
-
-find_x_expire(_, []) ->
-    never;
-find_x_expire(TimeStamp, [{xmlcdata, _} | Els]) ->
-    find_x_expire(TimeStamp, Els);
-find_x_expire(TimeStamp, [El | Els]) ->
-    case xml:get_tag_attr_s("xmlns", El) of
-       ?NS_EXPIRE ->
-           Val = xml:get_tag_attr_s("seconds", El),
-           case catch list_to_integer(Val) of
-               {'EXIT', _} ->
-                   never;
-               Int when Int > 0 ->
-                   {MegaSecs, Secs, MicroSecs} = TimeStamp,
-                   S = MegaSecs * 1000000 + Secs + Int,
-                   MegaSecs1 = S div 1000000,
-                   Secs1 = S rem 1000000,
-                   {MegaSecs1, Secs1, MicroSecs};
-               _ ->
-                   never
-           end;
-       _ ->
-           find_x_expire(TimeStamp, Els)
-    end.
-
-
-pop_offline_messages(Ls, User, Server) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Username = list_to_binary(LUser),
-    case ejabberd_riak:get_objects_by_index(
-           LServer, <<"offline">>, <<"user_bin">>, Username) of
-        {ok, Rs} ->
-            SortedRs =
-                lists:sort(fun(X, Y) ->
-                                   MX = riak_object:get_metadata(X),
-                                   {ok, IX} = dict:find(<<"index">>, MX),
-                                   {value, TSX} = lists:keysearch(
-                                                    <<"timestamp_bin">>, 1,
-                                                    IX),
-                                   MY = riak_object:get_metadata(Y),
-                                   {ok, IY} = dict:find(<<"index">>, MY),
-                                   {value, TSY} = lists:keysearch(
-                                                    <<"timestamp_bin">>, 1,
-                                                    IY),
-                                   TSX =< TSY
-                           end, Rs),
-            Ls ++ lists:flatmap(
-                   fun(R) ->
-                            Key = riak_object:key(R),
-                            ejabberd_riak:delete(LServer, <<"offline">>, Key),
-                            XML = riak_object:get_value(R),
-                           case xml_stream:parse_element(XML) of
-                               {error, _Reason} ->
-                                   [];
-                               El ->
-                                   To = jlib:string_to_jid(
-                                          xml:get_tag_attr_s("to", El)),
-                                   From = jlib:string_to_jid(
-                                            xml:get_tag_attr_s("from", El)),
-                                   if
-                                       (To /= error) and
-                                       (From /= error) ->
-                                           [{route, From, To, El}];
-                                       true ->
-                                           []
-                                   end
-                           end
-                   end, SortedRs);
-       _ ->
-           Ls
-    end.
-
-
-remove_user(User, Server) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Username = list_to_binary(LUser),
-    case ejabberd_riak:get_keys_by_index(
-           LServer, <<"offline">>, <<"user_bin">>, Username) of
-        {ok, Keys} ->
-            lists:foreach(
-              fun(Key) ->
-                      ejabberd_riak:delete(LServer, <<"offline">>, Key)
-              end, Keys);
-        _ ->
-            ok
-    end.
-
-
-%% Helper functions:
-
-%% TODO: Warning - This function is a duplicate from mod_offline.erl
-%% It is duplicate to stay consistent (many functions are duplicated
-%% in this module). It will be refactored later on.
-%% Warn senders that their messages have been discarded:
-discard_warn_sender(Msgs) ->
-    lists:foreach(
-      fun(#offline_msg{from=From, to=To, packet=Packet}) ->
-             ErrText = "Your contact offline message queue is full. The message has been discarded.",
-             Lang = xml:get_tag_attr_s("xml:lang", Packet),
-             Err = jlib:make_error_reply(
-                     Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)),
-             ejabberd_router:route(
-               To,
-               From, Err)
-      end, Msgs).
-
-
-webadmin_page(_, Host,
-             #request{us = _US,
-                      path = ["user", U, "queue"],
-                      q = Query,
-                      lang = Lang} = _Request) ->
-    Res = user_queue(U, Host, Query, Lang),
-    {stop, Res};
-
-webadmin_page(Acc, _, _) -> Acc.
-
-user_queue(User, Server, Query, Lang) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Username = ejabberd_odbc:escape(LUser),
-    US = {LUser, LServer},
-    Res = user_queue_parse_query(Username, LServer, Query),
-    Msgs = case catch ejabberd_odbc:sql_query(
-                       LServer,
-                       ["select username, xml from spool"
-                        "  where username='", Username, "'"
-                        "  order by seq;"]) of
-              {selected, ["username", "xml"], Rs} ->
-                  lists:flatmap(
-                    fun({_, XML}) ->
-                            case xml_stream:parse_element(XML) of
-                                {error, _Reason} ->
-                                    [];
-                                El ->
-                                    [El]
-                            end
-                    end, Rs);
-              _ ->
-                  []
-          end,
-    FMsgs =
-       lists:map(
-         fun({xmlelement, _Name, _Attrs, _Els} = Msg) ->
-                 ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg))),
-                 Packet = Msg,
-                 FPacket = ejabberd_web_admin:pretty_print_xml(Packet),
-                 ?XE("tr",
-                     [?XAE("td", [{"class", "valign"}], [?INPUT("checkbox", "selected", ID)]),
-                      ?XAE("td", [{"class", "valign"}], [?XC("pre", FPacket)])]
-                    )
-         end, Msgs),
-    [?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
-                            [us_to_list(US)]))] ++
-       case Res of
-           ok -> [?XREST("Submitted")];
-           nothing -> []
-       end ++
-       [?XAE("form", [{"action", ""}, {"method", "post"}],
-             [?XE("table",
-                  [?XE("thead",
-                       [?XE("tr",
-                            [?X("td"),
-                             ?XCT("td", "Packet")
-                            ])]),
-                   ?XE("tbody",
-                       if
-                           FMsgs == [] ->
-                               [?XE("tr",
-                                    [?XAC("td", [{"colspan", "4"}], " ")]
-                                   )];
-                           true ->
-                               FMsgs
-                       end
-                      )]),
-              ?BR,
-              ?INPUTT("submit", "delete", "Delete Selected")
-             ])].
-
-user_queue_parse_query(Username, LServer, Query) ->
-    case lists:keysearch("delete", 1, Query) of
-       {value, _} ->
-           Msgs = case catch ejabberd_odbc:sql_query(
-                               LServer,
-                               ["select xml, seq from spool"
-                                "  where username='", Username, "'"
-                                "  order by seq;"]) of
-                      {selected, ["xml", "seq"], Rs} ->
-                          lists:flatmap(
-                            fun({XML, Seq}) ->
-                                    case xml_stream:parse_element(XML) of
-                                        {error, _Reason} ->
-                                            [];
-                                        El ->
-                                            [{El, Seq}]
-                                    end
-                            end, Rs);
-                      _ ->
-                          []
-                  end,
-           F = fun() ->
-                       lists:foreach(
-                         fun({Msg, Seq}) ->
-                                 ID = jlib:encode_base64(
-                                        binary_to_list(term_to_binary(Msg))),
-                                 case lists:member({"selected", ID}, Query) of
-                                     true ->
-                                         SSeq = ejabberd_odbc:escape(Seq),
-                                         catch ejabberd_odbc:sql_query(
-                                                 LServer,
-                                                 ["delete from spool"
-                                                  "  where username='", Username, "'"
-                                                  "  and seq='", SSeq, "';"]);
-                                     false ->
-                                         ok
-                                 end
-                         end, Msgs)
-               end,
-           mnesia:transaction(F),
-           ok;
-       false ->
-           nothing
-    end.
-
-us_to_list({User, Server}) ->
-    jlib:jid_to_string({User, Server, ""}).
-
-webadmin_user(Acc, User, Server, Lang) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Username = ejabberd_odbc:escape(LUser),
-    QueueLen = case catch ejabberd_odbc:sql_query(
-                           LServer,
-                           ["select count(*) from spool"
-                            "  where username='", Username, "';"]) of
-                  {selected, [_], [{SCount}]} ->
-                      SCount;
-                  _ ->
-                      0
-              end,
-    FQueueLen = [?AC("queue/", QueueLen)],
-    Acc ++ [?XCT("h3", "Offline Messages:")] ++ FQueueLen ++ [?C(" "), ?INPUTT("submit", "removealloffline", "Remove All Offline Messages")].
-
-webadmin_user_parse_query(_, "removealloffline", User, Server, _Query) ->
-    case catch odbc_queries:del_spool_msg(Server, User) of
-         {'EXIT', Reason} ->
-            ?ERROR_MSG("Failed to remove offline messages: ~p", [Reason]),
-            {stop, error};
-         {error, Reason} ->
-            ?ERROR_MSG("Failed to remove offline messages: ~p", [Reason]),
-            {stop, error};
-         _ ->
-            ?INFO_MSG("Removed all offline messages for ~s@~s", [User, Server]),
-            {stop, ok}
-    end;
-webadmin_user_parse_query(Acc, _Action, _User, _Server, _Query) ->
-    Acc.
-
-%% ------------------------------------------------
-%% mod_offline: number of messages quota management
-
-%% Returns as integer the number of offline messages for a given user
-count_offline_messages(LUser, LServer) ->
-    Username = list_to_binary([LUser, $@, LServer]),
-    case catch ejabberd_riak:count_by_index(
-                 LServer, <<"offline">>, <<"user_bin">>, Username) of
-        {ok, Res} when is_integer(Res) ->
-            Res;
-        _ ->
-            0
-    end.
-
-count_offline_messages(_Acc, User, Server) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Num = case catch ejabberd_odbc:sql_query(
-                      LServer,
-                      ["select xml from spool"
-                       "  where username='", LUser, "';"]) of
-             {selected, ["xml"], Rs} ->
-                 lists:foldl(
-                   fun({XML}, Acc) ->
-                           case xml_stream:parse_element(XML) of
-                               {error, _Reason} ->
-                                   Acc;
-                               El ->
-                                   case xml:get_subtag(El, "body") of
-                                       false ->
-                                           Acc;
-                                       _ ->
-                                           Acc + 1
-                                   end
-                           end
-                   end, 0, Rs);
-             _ ->
-                 0
-         end,
-    {stop, Num}.
index 9fa74d9b7ecf3e6498fa3c7d4fc96e4fc5266357..301880e97fa684b154580c17a8b0fecd19544014 100644 (file)
@@ -89,7 +89,8 @@ process_sm_iq(#jid{luser = LUser, lserver = LServer},
                    end,
                case DBType of
                  odbc -> ejabberd_odbc:sql_transaction(LServer, F);
-                 mnesia -> mnesia:transaction(F)
+                 mnesia -> mnesia:transaction(F);
+                 riak -> F()
                end,
                IQ#iq{type = result, sub_el = []}
          end;
@@ -149,7 +150,15 @@ set_data(LUser, LServer, {XMLNS, El}, odbc) ->
     LXMLNS = ejabberd_odbc:escape(XMLNS),
     SData = ejabberd_odbc:escape(xml:element_to_binary(El)),
     odbc_queries:set_private_data(LServer, Username, LXMLNS,
-                                 SData).
+                                 SData);
+set_data(LUser, LServer, {XMLNS, El}, riak) ->
+    Username = LUser,
+    Key = <<LUser/binary, $@, LServer/binary, $@, XMLNS/binary>>,
+    SData = xml:element_to_binary(El),
+    ejabberd_riak:put(
+      LServer, <<"private">>, Key, SData,
+      [{<<"user_bin">>, Username}]),
+    ok.
 
 get_data(LUser, LServer, Data) ->
     get_data(LUser, LServer,
@@ -182,10 +191,19 @@ get_data(LUser, LServer, odbc, [{XMLNS, El} | Els],
            Data when is_record(Data, xmlel) ->
                get_data(LUser, LServer, odbc, Els, [Data | Res])
          end;
-      %% MREMOND: I wonder when the query could return a vcard ?
-      {selected, [<<"vcard">>], []} ->
-         get_data(LUser, LServer, odbc, Els, [El | Res]);
       _ -> get_data(LUser, LServer, odbc, Els, [El | Res])
+    end;
+get_data(LUser, LServer, riak, [{XMLNS, El} | Els],
+        Res) ->
+    Key = <<LUser/binary, $@, LServer/binary, $@, XMLNS/binary>>,
+    case ejabberd_riak:get(LServer, <<"private">>, Key) of
+        {ok, SData} ->
+            case xml_stream:parse_element(SData) of
+                Data when element(1, Data) == xmlelement ->
+                    get_data(LUser, LServer, riak, Els, [Data | Res])
+            end;
+        _ -> 
+            get_data(LUser, LServer, riak, Els, [El | Res])
     end.
 
 
@@ -214,6 +232,23 @@ get_all_data(LUser, LServer, odbc) ->
               end, Res);
         _ ->
             []
+    end;
+get_all_data(LUser, LServer, riak) ->
+    Username = LUser,
+    case ejabberd_riak:get_by_index(
+           LServer, <<"private">>, <<"user_bin">>, Username) of
+        {ok, Res} ->
+            lists:flatmap(
+              fun(SData) ->
+                      case xml_stream:parse_element(SData) of
+                          #xmlel{} = El ->
+                              [El];
+                          _ ->
+                              []
+                      end
+              end, Res);
+        _ ->
+            []
     end.
 
 remove_user(User, Server) ->
@@ -242,7 +277,19 @@ remove_user(LUser, LServer, mnesia) ->
 remove_user(LUser, LServer, odbc) ->
     Username = ejabberd_odbc:escape(LUser),
     odbc_queries:del_user_private_storage(LServer,
-                                         Username).
+                                         Username);
+remove_user(LUser, LServer, riak) ->
+    Username = LUser,
+    case ejabberd_riak:get_keys_by_index(
+           LServer, <<"private">>, <<"user_bin">>, Username) of
+        {ok, Keys} ->
+            lists:foreach(
+              fun(Key) ->
+                      ejabberd_riak:delete(LServer, <<"private">>, Key)
+              end, Keys);
+        _ ->
+            ok
+    end.
 
 update_table() ->
     Fields = record_info(fields, private_storage),
diff --git a/src/mod_private_riak.erl b/src/mod_private_riak.erl
deleted file mode 100644 (file)
index e1b4f89..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File    : mod_private_riak.erl
-%%% Author  : Alexey Shchepin <alexey@process-one.net>
-%%% Purpose : Private storage support
-%%% Created :  6 Jan 2012 by Alexey Shchepin <alexey@process-one.net>
-%%%
-%%%
-%%% ejabberd, Copyright (C) 2002-2011   ProcessOne
-%%%
-%%% This program is free software; you can redistribute it and/or
-%%% modify it under the terms of the GNU General Public License as
-%%% published by the Free Software Foundation; either version 2 of the
-%%% License, or (at your option) any later version.
-%%%
-%%% This program is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-%%% General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License
-%%% along with this program; if not, write to the Free Software
-%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-%%% 02111-1307 USA
-%%%
-%%%----------------------------------------------------------------------
-
--module(mod_private_riak).
--author('alexey@process-one.net').
-
--behaviour(gen_mod).
-
--export([start/2,
-        stop/1,
-        process_sm_iq/3,
-        remove_user/2]).
-
--include("ejabberd.hrl").
--include("jlib.hrl").
-
-start(Host, Opts) ->
-    IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
-    ejabberd_hooks:add(remove_user, Host,
-                      ?MODULE, remove_user, 50),
-    gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE,
-                                 ?MODULE, process_sm_iq, IQDisc).
-
-stop(Host) ->
-    ejabberd_hooks:delete(remove_user, Host,
-                         ?MODULE, remove_user, 50),
-    gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE).
-
-
-process_sm_iq(From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
-    #jid{luser = LUser, lserver = LServer} = From,
-    case lists:member(LServer, ?MYHOSTS) of
-       true ->
-           {xmlelement, Name, Attrs, Els} = SubEl,
-           case Type of
-               set ->
-                    lists:foreach(
-                      fun(El) ->
-                              set_data(LUser, LServer, El)
-                      end, Els),
-                   IQ#iq{type = result,
-                         sub_el = [{xmlelement, Name, Attrs, []}]};
-               get ->
-                   case catch get_data(LUser, LServer, Els) of
-                       {'EXIT', _Reason} ->
-                           IQ#iq{type = error,
-                                 sub_el = [SubEl,
-                                           ?ERR_INTERNAL_SERVER_ERROR]};
-                       Res ->
-                           IQ#iq{type = result,
-                                 sub_el = [{xmlelement, Name, Attrs, Res}]}
-                   end
-           end;
-       false ->
-           IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
-    end.
-
-set_data(LUser, LServer, El) ->
-    case El of
-       {xmlelement, _Name, Attrs, _Els} ->
-           XMLNS = xml:get_attr_s("xmlns", Attrs),
-           case XMLNS of
-               "" ->
-                   ignore;
-               _ ->
-                    Username = list_to_binary(LUser),
-                    Key = list_to_binary([LUser, $@, LServer, $@, XMLNS]),
-                   SData = xml:element_to_binary(El),
-                    ejabberd_riak:put(
-                      LServer, <<"private">>, Key, SData,
-                      [{<<"user_bin">>, Username}]),
-                    ok
-           end;
-       _ ->
-           ignore
-    end.
-
-get_data(LUser, LServer, Els) ->
-    get_data(LUser, LServer, Els, []).
-
-get_data(_LUser, _LServer, [], Res) ->
-    lists:reverse(Res);
-get_data(LUser, LServer, [El | Els], Res) ->
-    case El of
-       {xmlelement, _Name, Attrs, _} ->
-           XMLNS = xml:get_attr_s("xmlns", Attrs),
-            Key = list_to_binary([LUser, $@, LServer, $@, XMLNS]),
-           case ejabberd_riak:get(LServer, <<"private">>, Key) of
-               {ok, SData} ->
-                   case xml_stream:parse_element(SData) of
-                       Data when element(1, Data) == xmlelement ->
-                           get_data(LUser, LServer, Els,
-                                    [Data | Res])
-                   end;
-                _ -> 
-                    get_data(LUser, LServer, Els, [El | Res])
-           end;
-       _ ->
-           get_data(LUser, LServer, Els, Res)
-    end.
-
-
-remove_user(User, Server) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Username = list_to_binary(LUser),
-    case ejabberd_riak:get_keys_by_index(
-           LServer, <<"private">>, <<"user_bin">>, Username) of
-        {ok, Keys} ->
-            lists:foreach(
-              fun(Key) ->
-                      ejabberd_riak:delete(LServer, <<"private">>, Key)
-              end, Keys);
-        _ ->
-            ok
-    end.
index 01646229f68b6d3f69c81c377522f0a025f058c6..8ef70eb598540cba8a6222a84b9070613dcbea00 100644 (file)
@@ -204,6 +204,13 @@ read_roster_version(LUser, LServer, odbc) ->
        of
       {selected, [<<"version">>], [[Version]]} -> Version;
       {selected, [<<"version">>], []} -> error
+    end;
+read_roster_version(LServer, LUser, riak) ->
+    Username = LUser,
+    case ejabberd_riak:get(LServer, <<"roster_version">>,
+                           Username) of
+        {ok, Version} -> Version;
+        {error, notfound} -> error
     end.
 
 write_roster_version(LUser, LServer) ->
@@ -239,7 +246,11 @@ write_roster_version(LUser, LServer, InTransaction, Ver,
                                                odbc_queries:set_roster_version(Username,
                                                                                EVer)
                                        end)
-    end.
+    end;
+write_roster_version(LUser, LServer, _InTransaction, Ver,
+                    riak) ->
+    Username = LUser,
+    riak_set_roster_version(LServer, Username, Ver).
 
 %% Load roster from DB only if neccesary. 
 %% It is neccesary if
@@ -388,6 +399,37 @@ get_roster(LUser, LServer, odbc) ->
                                 Items),
          RItems;
       _ -> []
+    end;
+get_roster(LUser, LServer, riak) ->
+    Username = LUser,
+    case catch riak_get_roster(LServer, Username) of
+       {ok, Items} when is_list(Items) ->
+           JIDGroups = case riak_get_roster_jid_groups(LServer, Username) of
+                           {ok, JGrps} when is_list(JGrps) ->
+                               JGrps;
+                           _ ->
+                               []
+                       end,
+            GroupsDict = dict:from_list(JIDGroups),
+           RItems = lists:flatmap(
+                      fun(I) ->
+                              case riak_raw_to_record(LServer, I) of
+                                  %% Bad JID in database:
+                                  error ->
+                                      [];
+                                  R ->
+                                      SJID = jlib:jid_to_string(R#roster.jid),
+                                      Groups =
+                                           case dict:find(SJID, GroupsDict) of
+                                               {ok, Gs} -> Gs;
+                                               error -> []
+                                           end,
+                                      [R#roster{groups = Groups}]
+                              end
+                      end, Items),
+           RItems;
+       _ ->
+           []
     end.
 
 item_to_xml(Item) ->
@@ -455,6 +497,31 @@ get_roster_by_jid_t(LUser, LServer, LJID, odbc) ->
                R#roster{usj = {LUser, LServer, LJID},
                         us = {LUser, LServer}, jid = LJID, name = <<"">>}
          end
+    end;
+get_roster_by_jid_t(LUser, LServer, LJID, riak) ->
+    Username = LUser,
+    SJID = jlib:jid_to_string(LJID),
+    Res = riak_get_roster_by_jid(LServer, Username, SJID),
+    case Res of
+        {error, _} ->
+            #roster{usj = {LUser, LServer, LJID},
+                    us = {LUser, LServer},
+                    jid = LJID};
+        {ok, I} ->
+            R = riak_raw_to_record(LServer, I),
+            case R of
+                %% Bad JID in database:
+                error ->
+                    #roster{usj = {LUser, LServer, LJID},
+                            us = {LUser, LServer},
+                            jid = LJID};
+                _ ->
+                    R#roster{
+                      usj = {LUser, LServer, LJID},
+                      us = {LUser, LServer},
+                      jid = LJID,
+                      name = ""}
+            end
     end.
 
 try_process_iq_set(From, To, #iq{sub_el = SubEl} = IQ) ->
@@ -631,8 +698,16 @@ get_subscription_lists(_, LUser, LServer, odbc) ->
        <<"server">>, <<"subscribe">>, <<"type">>],
        Items}
          when is_list(Items) ->
-         Items;
+            lists:map(fun(I) -> raw_to_record(LServer, I) end, Items);
       _ -> []
+    end;
+get_subscription_lists(_, LUser, LServer, riak) ->
+    Username = LUser,
+    case catch riak_get_roster(LServer, Username) of
+       {ok, Items} when is_list(Items) ->
+            lists:map(fun(I) -> riak_raw_to_record(LServer, I) end, Items);
+       _ ->
+           []
     end.
 
 fill_subscription_lists(LServer, [#roster{} = I | Is],
@@ -671,12 +746,18 @@ roster_subscribe_t(LUser, LServer, LJID, Item, odbc) ->
     Username = ejabberd_odbc:escape(LUser),
     SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
     odbc_queries:roster_subscribe(LServer, Username, SJID,
-                                 ItemVals).
+                                 ItemVals);
+roster_subscribe_t(LUser, LServer, LJID, Item, riak) ->
+    ItemVals = riak_record_to_string(Item),
+    Username = LUser,
+    SJID = jlib:jid_to_string(LJID),
+    riak_roster_subscribe(LServer, Username, SJID, ItemVals).
 
 transaction(LServer, F) ->
     case gen_mod:db_type(LServer, ?MODULE) of
       mnesia -> mnesia:transaction(F);
-      odbc -> ejabberd_odbc:sql_transaction(LServer, F)
+      odbc -> ejabberd_odbc:sql_transaction(LServer, F);
+      riak -> {atomic, F()}
     end.
 
 in_subscription(_, User, Server, JID, Type, Reason) ->
@@ -727,6 +808,25 @@ get_roster_by_jid_with_groups_t(LUser, LServer, LJID,
        []} ->
          #roster{usj = {LUser, LServer, LJID},
                  us = {LUser, LServer}, jid = LJID}
+    end;
+get_roster_by_jid_with_groups_t(LUser, LServer, LJID, riak) ->
+    Username = LUser,
+    SJID = jlib:jid_to_string(LJID),
+    case riak_get_roster_by_jid(LServer, Username, SJID) of
+        {ok, I} ->
+            R = riak_raw_to_record(LServer, I),
+            Groups =
+                case riak_get_roster_groups(LServer, Username, SJID) of
+                    {ok, JGrps} when is_list(JGrps) ->
+                        JGrps;
+                    _ ->
+                        []
+                end,
+            R#roster{groups = Groups};
+        {error, _} ->
+            #roster{usj = {LUser, LServer, LJID},
+                    us = {LUser, LServer},
+                    jid = LJID}
     end.
 
 process_subscription(Direction, User, Server, JID1,
@@ -924,12 +1024,12 @@ in_auto_reply(_, _, _) -> none.
 remove_user(User, Server) ->
     LUser = jlib:nodeprep(User),
     LServer = jlib:nameprep(Server),
+    send_unsubscription_to_rosteritems(LUser, LServer),
     remove_user(LUser, LServer,
                gen_mod:db_type(LServer, ?MODULE)).
 
 remove_user(LUser, LServer, mnesia) ->
     US = {LUser, LServer},
-    send_unsubscription_to_rosteritems(LUser, LServer),
     F = fun () ->
                lists:foreach(fun (R) -> mnesia:delete_object(R) end,
                              mnesia:index_read(roster, US, #roster.us))
@@ -937,8 +1037,11 @@ remove_user(LUser, LServer, mnesia) ->
     mnesia:transaction(F);
 remove_user(LUser, LServer, odbc) ->
     Username = ejabberd_odbc:escape(LUser),
-    send_unsubscription_to_rosteritems(LUser, LServer),
     odbc_queries:del_user_roster_t(LServer, Username),
+    ok;
+remove_user(LUser, LServer, riak) ->
+    Username = LUser,
+    riak_del_user_roster(LServer, Username),
     ok.
 
 %% For each contact with Subscription:
@@ -1009,7 +1112,15 @@ update_roster_t(LUser, LServer, LJID, Item, odbc) ->
     SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
     ItemVals = record_to_string(Item),
     ItemGroups = groups_to_string(Item),
-    odbc_queries:update_roster(LServer, Username, SJID, ItemVals, ItemGroups).
+    odbc_queries:update_roster(LServer, Username, SJID, ItemVals,
+                               ItemGroups);
+update_roster_t(LUser, LServer, LJID, Item, riak) ->
+    Username = LUser,
+    SJID = jlib:jid_to_string(LJID),
+    ItemVals = riak_record_to_string(Item),
+    ItemGroups = riak_groups_to_binary(Item),
+    riak_update_roster(
+      LServer, Username, SJID, ItemVals, ItemGroups).
 
 del_roster_t(LUser, LServer, LJID) ->
     DBType = gen_mod:db_type(LServer, ?MODULE),
@@ -1020,7 +1131,11 @@ del_roster_t(LUser, LServer, LJID, mnesia) ->
 del_roster_t(LUser, LServer, LJID, odbc) ->
     Username = ejabberd_odbc:escape(LUser),
     SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
-    odbc_queries:del_roster(LServer, Username, SJID).
+    odbc_queries:del_roster(LServer, Username, SJID);
+del_roster_t(LUser, LServer, LJID, riak) ->
+    Username = LUser,
+    SJID = jlib:jid_to_string(LJID),
+    riak_del_roster(LServer, Username, SJID).
 
 process_item_set_t(LUser, LServer,
                   #xmlel{attrs = Attrs, children = Els}) ->
@@ -1161,6 +1276,44 @@ get_in_pending_subscriptions(Ls, User, Server, odbc) ->
                                    end,
                                    Items));
       _ -> Ls
+    end;
+get_in_pending_subscriptions(Ls, User, Server, riak) ->
+    JID = jlib:make_jid(User, Server, <<"">>),
+    LUser = JID#jid.luser,
+    LServer = JID#jid.lserver,
+    Username = LUser,
+    case catch riak_get_roster(LServer, Username) of
+       {ok, Items} when is_list(Items) ->
+           Ls ++ lists:map(
+                   fun(R) ->
+                           Message = R#roster.askmessage,
+                            #xmlel{name = <<"presence">>,
+                                   attrs = [{<<"from">>,
+                                             jlib:jid_to_string(R#roster.jid)},
+                                            {<<"to">>, jlib:jid_to_string(JID)},
+                                            {<<"type">>, <<"subscribe">>}],
+                                   children = [#xmlel{name = <<"status">>,
+                                                      attrs = [],
+                                                      children =
+                                                      [{xmlcdata, Message}]}]}
+                   end,
+                   lists:flatmap(
+                     fun(I) ->
+                             case riak_raw_to_record(LServer, I) of
+                                 %% Bad JID in database:
+                                 error ->
+                                     [];
+                                 R ->
+                                     case R#roster.ask of
+                                         in   -> [R];
+                                         both -> [R];
+                                         _ -> []
+                                     end
+                             end
+                     end,
+                     Items));
+       _ ->
+           Ls
     end.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1205,6 +1358,21 @@ read_subscription_and_groups(LUser, LServer, LJID,
                   end,
          {Subscription, Groups};
       _ -> error
+    end;
+read_subscription_and_groups(LUser, LServer, LJID,
+                            riak) ->
+    Username = LUser,
+    SJID = jlib:jid_to_string(LJID),
+    case catch riak_get_subscription(LServer, Username, SJID) of
+       {ok, Subscription} ->
+           Groups = case riak_get_roster_jid_groups(LServer, Username) of
+                         {ok, JGrps} when is_list(JGrps) ->
+                             JGrps;
+                         _ ->
+                             []
+                     end,
+         {Subscription, Groups};
+      _ -> error
     end.
 
 get_jid_info(_, User, Server, JID) ->
@@ -1695,3 +1863,182 @@ import(_LServer, mnesia, #roster_version{} = RV) ->
     mnesia:dirty_write(RV);
 import(_, _, _) ->
     pass.
+
+riak_get_roster(LServer, Username) ->
+    ejabberd_riak:get_by_index(
+      LServer, <<"roster">>, <<"user_bin">>, Username).
+
+riak_get_roster_jid_groups(LServer, Username) ->
+    case ejabberd_riak:get_by_index(
+           LServer, <<"roster_groups">>, <<"user_bin">>, Username) of
+        {ok, JGs} ->
+            Res = lists:map(fun riak_binary_to_groups/1, JGs),
+            {ok, Res};
+        Error -> Error
+    end.
+
+riak_get_roster_groups(LServer, Username, SJID) ->
+    Key = <<Username/binary, $/, SJID/binary>>,
+    case ejabberd_riak:get(LServer, <<"roster_groups">>, Key) of
+        {ok, Gs} ->
+            {_, Res} = riak_binary_to_groups(Gs),
+            {ok, Res};
+        {error, notfound} ->
+            {ok, []};
+        Error -> Error
+    end.
+
+riak_get_roster_by_jid(LServer, Username, SJID) ->
+    Key = <<Username/binary, $/, SJID/binary>>,
+    ejabberd_riak:get(LServer, <<"roster">>, Key).
+
+riak_del_roster(LServer, Username, SJID) ->
+    Key = <<Username/binary, $/, SJID/binary>>,
+    ejabberd_riak:delete(LServer, <<"roster">>, Key).
+
+riak_update_roster(LServer, Username, SJID, ItemVals, ItemGroups) ->
+    Key = <<Username/binary, $/, SJID/binary>>,
+    ejabberd_riak:put(
+      LServer, <<"roster">>, Key, ItemVals,
+      [{<<"user_bin">>, Username}]),
+    ejabberd_riak:put(
+      LServer, <<"roster_groups">>, Key, ItemGroups,
+      [{<<"user_bin">>, Username}]).
+
+riak_roster_subscribe(LServer, Username, SJID, ItemVals) ->
+    Key = <<Username/binary, $/, SJID/binary>>,
+    ejabberd_riak:put(
+      LServer, <<"roster">>, Key, ItemVals,
+      [{<<"user_bin">>, Username}]).
+
+riak_get_subscription(LServer, Username, SJID) ->
+    case riak_get_roster_by_jid(LServer, Username, SJID) of
+        {ok, SR} ->
+            case riak_raw_to_record(LServer, SR) of
+                error ->
+                    {error, bad_record};
+                R ->
+                    {ok, R#roster.subscription}
+            end;
+        Error ->
+            Error
+    end.
+
+riak_set_roster_version(LServer, Username, RosterVersion) ->
+    ejabberd_riak:put(LServer, <<"roster_version">>,
+                      Username, RosterVersion).
+
+
+riak_del_user_roster(LServer, Username) ->
+    case ejabberd_riak:get_keys_by_index(
+           LServer, <<"roster">>, <<"user_bin">>, Username) of
+        {ok, Keys} ->
+            lists:foreach(
+              fun(Key) ->
+                      ejabberd_riak:delete(LServer, <<"roster">>, Key)
+              end, Keys);
+        _ ->
+            ok
+    end,
+    case ejabberd_riak:get_keys_by_index(
+           LServer, <<"roster_groups">>, <<"user_bin">>, Username) of
+        {ok, GKeys} ->
+            lists:foreach(
+              fun(Key) ->
+                      ejabberd_riak:delete(LServer, <<"roster_groups">>, Key)
+              end, GKeys);
+        _ ->
+            ok
+    end,
+    ejabberd_riak:delete(LServer, <<"roster_version">>, Username).
+
+riak_raw_to_record(LServer,
+              <<UsernameLen:16, Username:UsernameLen/binary,
+               SJIDLen:16, SJID:SJIDLen/binary,
+               NickLen:16, Nick:NickLen/binary,
+               SSubscription, SAsk,
+               SAskMessageLen:16, SAskMessage:SAskMessageLen/binary>>) ->
+    User = Username,
+    case jlib:string_to_jid(SJID) of
+       error ->
+           error;
+       JID ->
+           LJID = jlib:jid_tolower(JID),
+           Subscription = case SSubscription of
+                              $B -> both;
+                              $T -> to;
+                              $F -> from;
+                              _ -> none
+                          end,
+           Ask = case SAsk of
+                     $S -> subscribe;
+                     $U -> unsubscribe;
+                     $B -> both;
+                     $O -> out;
+                     $I -> in;
+                     _ -> none
+                 end,
+           #roster{usj = {User, LServer, LJID},
+                   us = {User, LServer},
+                   jid = LJID,
+                   name = Nick,
+                   subscription = Subscription,
+                   ask = Ask,
+                   askmessage = SAskMessage}
+    end.
+
+riak_record_to_string(#roster{us = {User, _Server},
+                        jid = JID,
+                        name = Name,
+                        subscription = Subscription,
+                        ask = Ask,
+                        askmessage = AskMessage}) ->
+    Username = User,
+    UsernameLen = size(Username),
+    SJID = jlib:jid_to_string(jlib:jid_tolower(JID)),
+    SJIDLen = size(SJID),
+    Nick = Name,
+    NickLen = size(Nick),
+    SSubscription = case Subscription of
+                       both -> $B;
+                       to   -> $T;
+                       from -> $F;
+                       none -> $N
+                   end,
+    SAsk = case Ask of
+              subscribe   -> $S;
+              unsubscribe -> $U;
+              both        -> $B;
+              out         -> $O;
+              in          -> $I;
+              none        -> $N
+          end,
+    SAskMessage = iolist_to_binary(AskMessage),
+    SAskMessageLen = size(SAskMessage),
+    <<UsernameLen:16, Username/binary,
+     SJIDLen:16, SJID/binary,
+     NickLen:16, Nick/binary,
+     SSubscription, SAsk,
+     SAskMessageLen:16, SAskMessage/binary>>.
+
+riak_groups_to_binary(#roster{jid = JID, groups = Groups}) ->
+    SJID = jlib:jid_to_string(jlib:jid_tolower(JID)),
+    SJIDLen = size(SJID),
+    %% Empty groups do not need to be converted to string to be inserted in
+    %% the database
+    lists:foldl(
+      fun([], Acc) ->
+              Acc;
+        (Group, Acc) ->
+             G = Group,
+              Len = size(G),
+             <<Acc/binary, Len:16, G/binary>>
+      end, <<SJIDLen:16, SJID/binary>>, Groups).
+
+riak_binary_to_groups(<<Len:16, SJID:Len/binary, Rest/binary>>) ->
+    {SJID, riak_binary_to_groups(Rest, [])}.
+
+riak_binary_to_groups(<<Len:16, G:Len/binary, Rest/binary>>, Res) ->
+    riak_binary_to_groups(Rest, [G | Res]);
+riak_binary_to_groups(_, Res) ->
+    Res.
diff --git a/src/mod_roster_riak.erl b/src/mod_roster_riak.erl
deleted file mode 100644 (file)
index e66800b..0000000
+++ /dev/null
@@ -1,1310 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File    : mod_roster_riak.erl
-%%% Author  : Alexey Shchepin <alexey@process-one.net>
-%%% Purpose : Roster management
-%%% Created :  6 Jan 2012 by Alexey Shchepin <alexey@process-one.net>
-%%%
-%%%
-%%% ejabberd, Copyright (C) 2002-2011   ProcessOne
-%%%
-%%% This program is free software; you can redistribute it and/or
-%%% modify it under the terms of the GNU General Public License as
-%%% published by the Free Software Foundation; either version 2 of the
-%%% License, or (at your option) any later version.
-%%%
-%%% This program is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-%%% General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License
-%%% along with this program; if not, write to the Free Software
-%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-%%% 02111-1307 USA
-%%%
-%%%----------------------------------------------------------------------
-
-%%% @doc Roster management (Mnesia storage).
-%%%
-%%% Includes support for XEP-0237: Roster Versioning.
-%%% The roster versioning follows an all-or-nothing strategy:
-%%%  - If the version supplied by the client is the latest, return an empty response.
-%%%  - If not, return the entire new roster (with updated version string).
-%%% Roster version is a hash digest of the entire roster.
-%%% No additional data is stored in DB.
-
--module(mod_roster_riak).
--author('alexey@process-one.net').
-
--behaviour(gen_mod).
-
--export([start/2, stop/1,
-        process_iq/3,
-        process_local_iq/3,
-        get_user_roster/2,
-        get_subscription_lists/3,
-        get_in_pending_subscriptions/3,
-        in_subscription/6,
-        out_subscription/4,
-        set_items/3,
-        remove_user/2,
-        get_jid_info/4,
-        webadmin_page/3,
-        webadmin_user/4,
-        get_versioning_feature/2,
-        roster_versioning_enabled/1]).
-
--include("ejabberd.hrl").
--include("jlib.hrl").
--include("mod_roster.hrl").
--include("web/ejabberd_http.hrl").
--include("web/ejabberd_web_admin.hrl").
-
-
-start(Host, _Opts) ->
-    IQDisc = no_queue,
-    ejabberd_hooks:add(roster_get, Host,
-                      ?MODULE, get_user_roster, 50),
-    ejabberd_hooks:add(roster_in_subscription, Host,
-                      ?MODULE, in_subscription, 50),
-    ejabberd_hooks:add(roster_out_subscription, Host,
-                      ?MODULE, out_subscription, 50),
-    ejabberd_hooks:add(roster_get_subscription_lists, Host,
-                      ?MODULE, get_subscription_lists, 50),
-    ejabberd_hooks:add(roster_get_jid_info, Host,
-                      ?MODULE, get_jid_info, 50),
-    ejabberd_hooks:add(remove_user, Host,
-                      ?MODULE, remove_user, 50),
-    ejabberd_hooks:add(anonymous_purge_hook, Host,
-                      ?MODULE, remove_user, 50),
-    ejabberd_hooks:add(resend_subscription_requests_hook, Host,
-                      ?MODULE, get_in_pending_subscriptions, 50),
-    ejabberd_hooks:add(roster_get_versioning_feature, Host,
-                      ?MODULE, get_versioning_feature, 50),
-    ejabberd_hooks:add(webadmin_page_host, Host,
-                      ?MODULE, webadmin_page, 50),
-    ejabberd_hooks:add(webadmin_user, Host,
-                      ?MODULE, webadmin_user, 50),
-    gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
-                                 ?MODULE, process_iq, IQDisc).
-
-stop(Host) ->
-    ejabberd_hooks:delete(roster_get, Host,
-                         ?MODULE, get_user_roster, 50),
-    ejabberd_hooks:delete(roster_in_subscription, Host,
-                         ?MODULE, in_subscription, 50),
-    ejabberd_hooks:delete(roster_out_subscription, Host,
-                         ?MODULE, out_subscription, 50),
-    ejabberd_hooks:delete(roster_get_subscription_lists, Host,
-                         ?MODULE, get_subscription_lists, 50),
-    ejabberd_hooks:delete(roster_get_jid_info, Host,
-                         ?MODULE, get_jid_info, 50),
-    ejabberd_hooks:delete(remove_user, Host,
-                         ?MODULE, remove_user, 50),
-    ejabberd_hooks:delete(anonymous_purge_hook, Host,
-                         ?MODULE, remove_user, 50),
-    ejabberd_hooks:delete(resend_subscription_requests_hook, Host,
-                      ?MODULE, get_in_pending_subscriptions, 50),
-    ejabberd_hooks:delete(roster_get_versioning_feature, Host,
-                         ?MODULE, get_versioning_feature, 50),
-    ejabberd_hooks:delete(webadmin_page_host, Host,
-                         ?MODULE, webadmin_page, 50),
-    ejabberd_hooks:delete(webadmin_user, Host,
-                         ?MODULE, webadmin_user, 50),
-    gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER).
-
-
-process_iq(From, To, IQ) ->
-    #iq{sub_el = SubEl} = IQ,
-    #jid{lserver = LServer} = From,
-    case lists:member(LServer, ?MYHOSTS) of
-       true ->
-           process_local_iq(From, To, IQ);
-       _ ->
-           IQ#iq{type = error, sub_el = [SubEl, ?ERR_ITEM_NOT_FOUND]}
-    end.
-
-process_local_iq(From, To, #iq{type = Type} = IQ) ->
-    case Type of
-       set ->
-           process_iq_set(From, To, IQ);
-       get ->
-           process_iq_get(From, To, IQ)
-    end.
-
-
-roster_hash(Items) ->
-    sha:sha(term_to_binary(
-              lists:sort(
-                [R#roster{groups = lists:sort(Grs)} || 
-                    R = #roster{groups = Grs} <- Items]))).
-
-roster_versioning_enabled(Host) ->
-    gen_mod:get_module_opt(Host, ?MODULE, versioning, false).
-
-roster_version_on_db(Host) ->
-    gen_mod:get_module_opt(Host, ?MODULE, store_current_id, false).
-
-%% Returns a list that may contain an xmlelement with the XEP-237 feature if it's enabled.
-get_versioning_feature(Acc, Host) ->
-    case roster_versioning_enabled(Host) of
-       true ->
-           Feature = {xmlelement,
-                      "ver",
-                      [{"xmlns", ?NS_ROSTER_VER}],
-                      [{xmlelement, "optional", [], []}]},
-           [Feature | Acc];
-       false -> []
-    end.
-
-roster_version(LServer, LUser) ->
-    US = {LUser, LServer},
-    Username = list_to_binary(LUser),
-    case roster_version_on_db(LServer) of
-        true ->
-            case ejabberd_riak:get(LServer, <<"roster_version">>,
-                                   Username) of
-                {ok, Version} -> Version;
-                {error, notfound} ->
-                    %% If for some reason we don't had it on DB. Create a version Id and store it.
-                    %% (we did the same on process_iq_get, that is called when client get roster,
-                    %%  not sure why it can still not be on DB at this point)
-                    RosterVersion = sha:sha(term_to_binary(now())),
-                    riak_set_roster_version(LServer, Username, RosterVersion),
-                    RosterVersion
-            end;
-        false ->
-            roster_hash(ejabberd_hooks:run_fold(roster_get, LServer, [], [US]))
-    end.
-
-%% Load roster from DB only if neccesary. 
-%% It is neccesary if
-%%     - roster versioning is disabled in server OR
-%%     - roster versioning is not used by the client OR
-%%     - roster versioning is used by server and client, BUT the server isn't storing versions on db OR
-%%     - the roster version from client don't match current version.
-process_iq_get(From, To, #iq{sub_el = SubEl} = IQ) ->
-    LUser = From#jid.luser,
-    LServer = From#jid.lserver,
-    US = {LUser, LServer},
-    Username = list_to_binary(LUser),
-
-    try
-        {ItemsToSend, VersionToSend} = 
-        case {xml:get_tag_attr("ver", SubEl), 
-              roster_versioning_enabled(LServer),
-              roster_version_on_db(LServer)} of
-            {{value, RequestedVersion}, true, true} ->
-                BRequestedVersion = iolist_to_binary(RequestedVersion),
-                %% Retrieve version from DB. Only load entire roster
-                %% when neccesary.
-                case ejabberd_riak:get(LServer, <<"roster_version">>,
-                                       Username) of
-                    {ok, BRequestedVersion} ->
-                        {false, false};
-                    {ok, NewVersion} ->
-                        {lists:map(fun item_to_xml/1, 
-                                   ejabberd_hooks:run_fold(roster_get, To#jid.lserver, [], [US])), NewVersion};
-                    {error, notfound} ->
-                        RosterVersion = sha:sha(term_to_binary(now())),
-                        ejabberd_riak:put(
-                          LServer, <<"roster_version">>,
-                          Username, list_to_binary(RosterVersion)),
-                        {lists:map(fun item_to_xml/1,
-                                   ejabberd_hooks:run_fold(roster_get, To#jid.lserver, [], [US])), RosterVersion}
-                end;
-
-            {{value, RequestedVersion}, true, false} ->
-                RosterItems = ejabberd_hooks:run_fold(roster_get, To#jid.lserver, [] , [US]),
-                case roster_hash(RosterItems) of
-                    RequestedVersion ->
-                        {false, false};
-                    New ->
-                        {lists:map(fun item_to_xml/1, RosterItems), New}
-                end;
-
-            _ ->
-                {lists:map(fun item_to_xml/1, 
-                           ejabberd_hooks:run_fold(roster_get, To#jid.lserver, [], [US])), false}
-        end,
-        IQ#iq{type = result,
-              sub_el = case {ItemsToSend, VersionToSend} of
-                           {false, false} ->
-                               [];
-                           {Items, false} ->
-                               [{xmlelement, "query",
-                                 [{"xmlns", ?NS_ROSTER}],
-                                 Items}];
-                           {Items, Version} ->
-                               [{xmlelement, "query",
-                                 [{"xmlns", ?NS_ROSTER},
-                                  {"ver", Version}],
-                                 Items}]
-                       end}
-    catch
-       _:_ ->  
-            IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}
-    end.
-
-
-get_user_roster(Acc, {LUser, LServer}) ->
-    Items = get_roster(LUser, LServer),
-    lists:filter(fun(#roster{subscription = none, ask = in}) ->
-                        false;
-                   (_) ->
-                        true
-                end, Items) ++ Acc.
-
-get_roster(LUser, LServer) ->
-    Username = list_to_binary(LUser),
-    case catch riak_get_roster(LServer, Username) of
-       {ok, Items} when is_list(Items) ->
-           JIDGroups = case riak_get_roster_jid_groups(LServer, Username) of
-                           {ok, JGrps} when is_list(JGrps) ->
-                               JGrps;
-                           _ ->
-                               []
-                       end,
-            GroupsDict = dict:from_list(JIDGroups),
-           RItems = lists:flatmap(
-                      fun(I) ->
-                              case raw_to_record(LServer, I) of
-                                  %% Bad JID in database:
-                                  error ->
-                                      [];
-                                  R ->
-                                      SJID = jlib:jid_to_string(R#roster.jid),
-                                      Groups =
-                                           case dict:find(SJID, GroupsDict) of
-                                               {ok, Gs} -> Gs;
-                                               error -> []
-                                           end,
-                                      [R#roster{groups = Groups}]
-                              end
-                      end, Items),
-           RItems;
-       _ ->
-           []
-    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];
-                from ->
-                    [{"subscription", "from"} | Attrs2];
-                to ->
-                    [{"subscription", "to"} | Attrs2];
-                both ->
-                    [{"subscription", "both"} | Attrs2];
-                remove ->
-                    [{"subscription", "remove"} | Attrs2]
-            end,
-    Attrs = case ask_to_pending(Item#roster.ask) of
-               out ->
-                   [{"ask", "subscribe"} | Attrs3];
-               both ->
-                   [{"ask", "subscribe"} | Attrs3];
-               _ ->
-                   Attrs3
-           end,
-    SubEls = lists:map(fun(G) ->
-                              {xmlelement, "group", [], [{xmlcdata, G}]}
-                      end, Item#roster.groups),
-    {xmlelement, "item", Attrs, SubEls}.
-
-
-process_iq_set(From, To, #iq{sub_el = SubEl} = IQ) ->
-    {xmlelement, _Name, _Attrs, Els} = SubEl,
-    lists:foreach(fun(El) -> process_item_set(From, To, El) end, Els),
-    IQ#iq{type = result, sub_el = []}.
-
-process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
-    JID1 = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
-    #jid{user = User, luser = LUser, lserver = LServer} = From,
-    case JID1 of
-       error ->
-           ok;
-       _ ->
-           LJID = jlib:jid_tolower(JID1),
-           Username = list_to_binary(LUser),
-           SJID = list_to_binary(jlib:jid_to_string(LJID)),
-           F = fun() ->
-                       Res = riak_get_roster_by_jid(LServer, Username, SJID),
-                       Item = case Res of
-                                  {error, _} ->
-                                      #roster{usj = {LUser, LServer, LJID},
-                                              us = {LUser, LServer},
-                                              jid = LJID};
-                                  {ok, I} ->
-                                      R = raw_to_record(LServer, I),
-                                      case R of
-                                          %% Bad JID in database:
-                                          error ->
-                                              #roster{usj = {LUser, LServer, LJID},
-                                                      us = {LUser, LServer},
-                                                      jid = LJID};
-                                          _ ->
-                                              R#roster{
-                                                usj = {LUser, LServer, LJID},
-                                                us = {LUser, LServer},
-                                                jid = LJID,
-                                                name = ""}
-                                      end
-                              end,
-                       Item1 = process_item_attrs(Item, Attrs),
-                       Item2 = process_item_els(Item1, Els),
-                       case Item2#roster.subscription of
-                           remove ->
-                                riak_del_roster(LServer, Username, SJID);
-                           _ ->
-                               ItemVals = record_to_string(Item2),
-                               ItemGroups = groups_to_binary(Item2),
-                               riak_update_roster(LServer, Username, SJID, ItemVals, ItemGroups)
-                       end,
-                       %% If the item exist in shared roster, take the
-                       %% subscription information from there:
-                       Item3 = ejabberd_hooks:run_fold(roster_process_item,
-                                                       LServer, Item2, [LServer]),
-                       case roster_version_on_db(LServer) of
-                            true ->
-                                RosterVersion = sha:sha(term_to_binary(now())),
-                                riak_set_roster_version(
-                                  LServer, Username, RosterVersion);
-                            false -> ok
-                       end,
-                       {ok, Item, Item3}
-               end,
-           case catch F() of
-               {ok, OldItem, Item} ->
-                   push_item(User, LServer, To, Item),
-                   case Item#roster.subscription of
-                       remove ->
-                           send_unsubscribing_presence(From, OldItem),
-                           ok;
-                       _ ->
-                           ok
-                   end;
-               E ->
-                   ?ERROR_MSG("ROSTER: roster item set error: ~p~n", [E]),
-                   ok
-           end
-    end;
-process_item_set(_From, _To, _) ->
-    ok.
-
-process_item_attrs(Item, [{Attr, Val} | Attrs]) ->
-    case Attr of
-       "jid" ->
-           case jlib:string_to_jid(Val) of
-               error ->
-                   process_item_attrs(Item, Attrs);
-               JID1 ->
-                   JID = {JID1#jid.luser, JID1#jid.lserver, JID1#jid.lresource},
-                   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);
-       _ ->
-           process_item_attrs(Item, Attrs)
-    end;
-process_item_attrs(Item, []) ->
-    Item.
-
-
-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);
-       _ ->
-           process_item_els(Item, Els)
-    end;
-process_item_els(Item, [{xmlcdata, _} | Els]) ->
-    process_item_els(Item, Els);
-process_item_els(Item, []) ->
-    Item.
-
-
-push_item(User, Server, From, Item) ->
-    ejabberd_sm:route(jlib:make_jid("", "", ""),
-                     jlib:make_jid(User, Server, ""),
-                     {xmlelement, "broadcast", [],
-                      [{item,
-                        Item#roster.jid,
-                        Item#roster.subscription}]}),
-    case roster_versioning_enabled(Server) of
-       true ->
-               push_item_version(Server, User, From, Item, roster_version(Server, User));
-       false ->
-           lists:foreach(fun(Resource) ->
-                         push_item(User, Server, Resource, From, Item)
-                 end, ejabberd_sm:get_user_resources(User, Server))
-    end.
-
-% TODO: don't push to those who not load roster
-push_item(User, Server, Resource, From, Item) ->
-    ResIQ = #iq{type = set, xmlns = ?NS_ROSTER,
-               id = "push" ++ randoms:get_string(),
-               sub_el = [{xmlelement, "query",
-                          [{"xmlns", ?NS_ROSTER}],
-                          [item_to_xml(Item)]}]},
-    ejabberd_router:route(
-      From,
-      jlib:make_jid(User, Server, Resource),
-      jlib:iq_to_xml(ResIQ)).
-
-%% @doc Roster push, calculate and include the version attribute.
-%% TODO: don't push to those who didn't load roster
-push_item_version(Server, User, From, Item, RosterVersion)  ->
-    lists:foreach(fun(Resource) ->
-                         push_item_version(User, Server, Resource, From, Item, RosterVersion)
-               end, ejabberd_sm:get_user_resources(User, Server)).
-
-push_item_version(User, Server, Resource, From, Item, RosterVersion) ->
-    IQPush = #iq{type = 'set', xmlns = ?NS_ROSTER,
-                id = "push" ++ randoms:get_string(),
-                sub_el = [{xmlelement, "query",
-                           [{"xmlns", ?NS_ROSTER},
-                            {"ver", RosterVersion}],
-                           [item_to_xml(Item)]}]},
-    ejabberd_router:route(
-      From,
-      jlib:make_jid(User, Server, Resource),
-      jlib:iq_to_xml(IQPush)).
-
-get_subscription_lists(_, User, Server) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Username = list_to_binary(LUser),
-    case catch riak_get_roster(LServer, Username) of
-       {ok, Items} when is_list(Items) ->
-           fill_subscription_lists(LServer, Items, [], []);
-       _ ->
-           {[], []}
-    end.
-
-fill_subscription_lists(LServer, [RawI | Is], F, T) ->
-    I = raw_to_record(LServer, RawI),
-    case I of
-       %% Bad JID in database:
-       error ->
-           fill_subscription_lists(LServer, Is, F, T);
-       _ ->
-           J = I#roster.jid,
-           case I#roster.subscription of
-               both ->
-                   fill_subscription_lists(LServer, Is, [J | F], [J | T]);
-               from ->
-                   fill_subscription_lists(LServer, Is, [J | F], T);
-               to ->
-                   fill_subscription_lists(LServer, Is, F, [J | T]);
-               _ ->
-                   fill_subscription_lists(LServer, Is, F, T)
-           end
-    end;
-fill_subscription_lists(_LServer, [], F, T) ->
-    {F, T}.
-
-ask_to_pending(subscribe) -> out;
-ask_to_pending(unsubscribe) -> none;
-ask_to_pending(Ask) -> Ask.
-
-
-
-in_subscription(_, User, Server, JID, Type, Reason) ->
-    process_subscription(in, User, Server, JID, Type, Reason).
-
-out_subscription(User, Server, JID, Type) ->
-    process_subscription(out, User, Server, JID, Type, []).
-
-process_subscription(Direction, User, Server, JID1, Type, Reason) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    LJID = jlib:jid_tolower(JID1),
-    Username = list_to_binary(LUser),
-    SJID = list_to_binary(jlib:jid_to_string(LJID)),
-    F = fun() ->
-               Item =
-                   case riak_get_roster_by_jid(LServer, Username, SJID) of
-                       {ok, I} ->
-                           %% raw_to_record can return error, but
-                           %% jlib_to_string would fail before this point
-                           R = raw_to_record(LServer, I),
-                           Groups =
-                               case riak_get_roster_groups(LServer, Username, SJID) of
-                                   {selected, ["grp"], JGrps} when is_list(JGrps) ->
-                                       [JGrp || {JGrp} <- JGrps];
-                                   _ ->
-                                       []
-                               end,
-                           R#roster{groups = Groups};
-                       {error, _} ->
-                           #roster{usj = {LUser, LServer, LJID},
-                                   us = {LUser, LServer},
-                                   jid = LJID}
-                   end,
-               NewState = case Direction of
-                              out ->
-                                  out_state_change(Item#roster.subscription,
-                                                   Item#roster.ask,
-                                                   Type);
-                              in ->
-                                  in_state_change(Item#roster.subscription,
-                                                  Item#roster.ask,
-                                                  Type)
-                          end,
-               AutoReply = case Direction of
-                               out ->
-                                   none;
-                               in ->
-                                   in_auto_reply(Item#roster.subscription,
-                                                 Item#roster.ask,
-                                                 Type)
-                           end,
-               AskMessage = case NewState of
-                                {_, both} -> Reason;
-                                {_, in}   -> Reason;
-                                _         -> ""
-                            end,
-               case NewState of
-                   none ->
-                       {ok, none, AutoReply};
-                   {none, none} when Item#roster.subscription == none,
-                                     Item#roster.ask == in ->
-                       riak_del_roster(LServer, Username, SJID),
-                       {ok, none, AutoReply};
-                   {Subscription, Pending} ->
-                       NewItem = Item#roster{subscription = Subscription,
-                                             ask = Pending,
-                                             askmessage = AskMessage},
-                       ItemVals = record_to_string(NewItem),
-                       riak_roster_subscribe(LServer, Username, SJID, ItemVals),
-                       case roster_version_on_db(LServer) of
-                            true ->
-                                riak_set_roster_version(
-                                  LServer, Username,
-                                  sha:sha(term_to_binary(now())));
-                            false -> ok
-                       end,
-                       {ok, {push, NewItem}, AutoReply}
-               end
-       end,
-    case catch F() of
-       {ok, Push, AutoReply} ->
-           case AutoReply of
-               none ->
-                   ok;
-               _ ->
-                   T = case AutoReply of
-                           subscribed -> "subscribed";
-                           unsubscribed -> "unsubscribed"
-                       end,
-                   ejabberd_router:route(
-                     jlib:make_jid(User, Server, ""), JID1,
-                     {xmlelement, "presence", [{"type", T}], []})
-           end,
-           case Push of
-               {push, Item} ->
-                   if
-                       Item#roster.subscription == none,
-                       Item#roster.ask == in ->
-                           ok;
-                       true ->
-                           push_item(User, Server,
-                                     jlib:make_jid(User, Server, ""), Item)
-                   end,
-                   true;
-               none ->
-                   false
-           end;
-       E ->
-            ?ERROR_MSG("subscription error: ~p~n", [E]),
-           false
-    end.
-
-
-%% in_state_change(Subscription, Pending, Type) -> NewState
-%% NewState = none | {NewSubscription, NewPending}
--ifdef(ROSTER_GATEWAY_WORKAROUND).
--define(NNSD, {to, none}).
--define(NISD, {to, in}).
--else.
--define(NNSD, none).
--define(NISD, none).
--endif.
-
-in_state_change(none, none, subscribe)    -> {none, in};
-in_state_change(none, none, subscribed)   -> ?NNSD;
-in_state_change(none, none, unsubscribe)  -> none;
-in_state_change(none, none, unsubscribed) -> none;
-in_state_change(none, out,  subscribe)    -> {none, both};
-in_state_change(none, out,  subscribed)   -> {to, none};
-in_state_change(none, out,  unsubscribe)  -> none;
-in_state_change(none, out,  unsubscribed) -> {none, none};
-in_state_change(none, in,   subscribe)    -> none;
-in_state_change(none, in,   subscribed)   -> ?NISD;
-in_state_change(none, in,   unsubscribe)  -> {none, none};
-in_state_change(none, in,   unsubscribed) -> none;
-in_state_change(none, both, subscribe)    -> none;
-in_state_change(none, both, subscribed)   -> {to, in};
-in_state_change(none, both, unsubscribe)  -> {none, out};
-in_state_change(none, both, unsubscribed) -> {none, in};
-in_state_change(to,   none, subscribe)    -> {to, in};
-in_state_change(to,   none, subscribed)   -> none;
-in_state_change(to,   none, unsubscribe)  -> none;
-in_state_change(to,   none, unsubscribed) -> {none, none};
-in_state_change(to,   in,   subscribe)    -> none;
-in_state_change(to,   in,   subscribed)   -> none;
-in_state_change(to,   in,   unsubscribe)  -> {to, none};
-in_state_change(to,   in,   unsubscribed) -> {none, in};
-in_state_change(from, none, subscribe)    -> none;
-in_state_change(from, none, subscribed)   -> {both, none};
-in_state_change(from, none, unsubscribe)  -> {none, none};
-in_state_change(from, none, unsubscribed) -> none;
-in_state_change(from, out,  subscribe)    -> none;
-in_state_change(from, out,  subscribed)   -> {both, none};
-in_state_change(from, out,  unsubscribe)  -> {none, out};
-in_state_change(from, out,  unsubscribed) -> {from, none};
-in_state_change(both, none, subscribe)    -> none;
-in_state_change(both, none, subscribed)   -> none;
-in_state_change(both, none, unsubscribe)  -> {to, none};
-in_state_change(both, none, unsubscribed) -> {from, none}.
-
-out_state_change(none, none, subscribe)    -> {none, out};
-out_state_change(none, none, subscribed)   -> none;
-out_state_change(none, none, unsubscribe)  -> none;
-out_state_change(none, none, unsubscribed) -> none;
-out_state_change(none, out,  subscribe)    -> {none, out}; %% We need to resend query (RFC3921, section 9.2)
-out_state_change(none, out,  subscribed)   -> none;
-out_state_change(none, out,  unsubscribe)  -> {none, none};
-out_state_change(none, out,  unsubscribed) -> none;
-out_state_change(none, in,   subscribe)    -> {none, both};
-out_state_change(none, in,   subscribed)   -> {from, none};
-out_state_change(none, in,   unsubscribe)  -> none;
-out_state_change(none, in,   unsubscribed) -> {none, none};
-out_state_change(none, both, subscribe)    -> none;
-out_state_change(none, both, subscribed)   -> {from, out};
-out_state_change(none, both, unsubscribe)  -> {none, in};
-out_state_change(none, both, unsubscribed) -> {none, out};
-out_state_change(to,   none, subscribe)    -> none;
-out_state_change(to,   none, subscribed)   -> {both, none};
-out_state_change(to,   none, unsubscribe)  -> {none, none};
-out_state_change(to,   none, unsubscribed) -> none;
-out_state_change(to,   in,   subscribe)    -> none;
-out_state_change(to,   in,   subscribed)   -> {both, none};
-out_state_change(to,   in,   unsubscribe)  -> {none, in};
-out_state_change(to,   in,   unsubscribed) -> {to, none};
-out_state_change(from, none, subscribe)    -> {from, out};
-out_state_change(from, none, subscribed)   -> none;
-out_state_change(from, none, unsubscribe)  -> none;
-out_state_change(from, none, unsubscribed) -> {none, none};
-out_state_change(from, out,  subscribe)    -> none;
-out_state_change(from, out,  subscribed)   -> none;
-out_state_change(from, out,  unsubscribe)  -> {from, none};
-out_state_change(from, out,  unsubscribed) -> {none, out};
-out_state_change(both, none, subscribe)    -> none;
-out_state_change(both, none, subscribed)   -> none;
-out_state_change(both, none, unsubscribe)  -> {from, none};
-out_state_change(both, none, unsubscribed) -> {to, none}.
-
-in_auto_reply(from, none, subscribe)    -> subscribed;
-in_auto_reply(from, out,  subscribe)    -> subscribed;
-in_auto_reply(both, none, subscribe)    -> subscribed;
-in_auto_reply(none, in,   unsubscribe)  -> unsubscribed;
-in_auto_reply(none, both, unsubscribe)  -> unsubscribed;
-in_auto_reply(to,   in,   unsubscribe)  -> unsubscribed;
-in_auto_reply(from, none, unsubscribe)  -> unsubscribed;
-in_auto_reply(from, out,  unsubscribe)  -> unsubscribed;
-in_auto_reply(both, none, unsubscribe)  -> unsubscribed;
-in_auto_reply(_,    _,    _)  ->           none.
-
-
-remove_user(User, Server) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Username = list_to_binary(LUser),
-    send_unsubscription_to_rosteritems(LUser, LServer),
-    riak_del_user_roster(LServer, Username),
-    ok.
-
-%% For each contact with Subscription:
-%% Both or From, send a "unsubscribed" presence stanza;
-%% Both or To, send a "unsubscribe" presence stanza.
-send_unsubscription_to_rosteritems(LUser, LServer) ->
-    RosterItems = get_user_roster([], {LUser, LServer}),
-    From = jlib:make_jid({LUser, LServer, ""}),
-    lists:foreach(fun(RosterItem) ->
-                         send_unsubscribing_presence(From, RosterItem)
-                 end,
-                 RosterItems).
-
-%% @spec (From::jid(), Item::roster()) -> ok
-send_unsubscribing_presence(From, Item) ->
-    IsTo = case Item#roster.subscription of
-              both -> true;
-              to -> true;
-              _ -> false
-          end,
-    IsFrom = case Item#roster.subscription of
-                both -> true;
-                from -> true;
-                _ -> false
-            end,
-    if IsTo ->
-           send_presence_type(
-             jlib:jid_remove_resource(From),
-             jlib:make_jid(Item#roster.jid), "unsubscribe");
-       true -> ok
-    end,
-    if IsFrom ->
-           send_presence_type(
-             jlib:jid_remove_resource(From),
-             jlib:make_jid(Item#roster.jid), "unsubscribed");
-       true -> ok
-    end,
-    ok.
-
-send_presence_type(From, To, Type) ->
-    ejabberd_router:route(
-      From, To,
-      {xmlelement, "presence",
-       [{"type", Type}],
-       []}).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-set_items(User, Server, SubEl) ->
-    {xmlelement, _Name, _Attrs, Els} = SubEl,
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    lists:foreach(fun(El) ->
-                          process_item_set_t(LUser, LServer, El)
-                  end, Els).
-
-process_item_set_t(LUser, LServer, {xmlelement, _Name, Attrs, Els}) ->
-    JID1 = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
-    case JID1 of
-       error ->
-           [];
-       _ ->
-           LJID = {JID1#jid.luser, JID1#jid.lserver, JID1#jid.lresource},
-           Username = list_to_binary(LUser),
-           SJID = list_to_binary(jlib:jid_to_string(LJID)),
-           Item = #roster{usj = {LUser, LServer, LJID},
-                          us = {LUser, LServer},
-                          jid = LJID},
-           Item1 = process_item_attrs_ws(Item, Attrs),
-           Item2 = process_item_els(Item1, Els),
-           case Item2#roster.subscription of
-               remove ->
-                   riak_del_roster(LServer, Username, SJID);
-               _ ->
-                   ItemVals = record_to_string(Item1),
-                   ItemGroups = groups_to_binary(Item2),
-                   riak_update_roster(
-                      LServer, Username, SJID, ItemVals, ItemGroups)
-           end
-    end;
-process_item_set_t(_LUser, _LServer, _) ->
-    [].
-
-process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) ->
-    case Attr of
-       "jid" ->
-           case jlib:string_to_jid(Val) of
-               error ->
-                   process_item_attrs_ws(Item, Attrs);
-               JID1 ->
-                   JID = {JID1#jid.luser, JID1#jid.lserver, JID1#jid.lresource},
-                   process_item_attrs_ws(Item#roster{jid = JID}, Attrs)
-           end;
-       "name" ->
-           process_item_attrs_ws(Item#roster{name = Val}, Attrs);
-       "subscription" ->
-           case Val of
-               "remove" ->
-                   process_item_attrs_ws(Item#roster{subscription = remove},
-                                         Attrs);
-               "none" ->
-                   process_item_attrs_ws(Item#roster{subscription = none},
-                                         Attrs);
-               "both" ->
-                   process_item_attrs_ws(Item#roster{subscription = both},
-                                         Attrs);
-               "from" ->
-                   process_item_attrs_ws(Item#roster{subscription = from},
-                                         Attrs);
-               "to" ->
-                   process_item_attrs_ws(Item#roster{subscription = to},
-                                         Attrs);
-               _ ->
-                   process_item_attrs_ws(Item, Attrs)
-           end;
-       "ask" ->
-           process_item_attrs_ws(Item, Attrs);
-       _ ->
-           process_item_attrs_ws(Item, Attrs)
-    end;
-process_item_attrs_ws(Item, []) ->
-    Item.
-
-get_in_pending_subscriptions(Ls, User, Server) ->
-    JID = jlib:make_jid(User, Server, ""),
-    LUser = JID#jid.luser,
-    LServer = JID#jid.lserver,
-    Username = list_to_binary(LUser),
-    case catch riak_get_roster(LServer, Username) of
-       {ok, Items} when is_list(Items) ->
-           Ls ++ lists:map(
-                   fun(R) ->
-                           Message = R#roster.askmessage,
-                           {xmlelement, "presence",
-                            [{"from", jlib:jid_to_string(R#roster.jid)},
-                             {"to", jlib:jid_to_string(JID)},
-                             {"type", "subscribe"}],
-                            [{xmlelement, "status", [],
-                              [{xmlcdata, Message}]}]}
-                   end,
-                   lists:flatmap(
-                     fun(I) ->
-                             case raw_to_record(LServer, I) of
-                                 %% Bad JID in database:
-                                 error ->
-                                     [];
-                                 R ->
-                                     case R#roster.ask of
-                                         in   -> [R];
-                                         both -> [R];
-                                         _ -> []
-                                     end
-                             end
-                     end,
-                     Items));
-       _ ->
-           Ls
-    end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-get_jid_info(_, User, Server, JID) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    LJID = jlib:jid_tolower(JID),
-    Username = list_to_binary(LUser),
-    SJID = list_to_binary(jlib:jid_to_string(LJID)),
-    case catch riak_get_subscription(LServer, Username, SJID) of
-       {ok, Subscription} ->
-           Groups =
-                case catch riak_get_roster_groups(LServer, Username, SJID) of
-                    {ok, JGrps} when is_list(JGrps) ->
-                        lists:map(fun binary_to_list/1, JGrps);
-                    _ ->
-                        []
-                end,
-           {Subscription, Groups};
-       _ ->
-           LRJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)),
-           if
-               LRJID == LJID ->
-                   {none, []};
-               true ->
-                   SRJID = list_to_binary(jlib:jid_to_string(LRJID)),
-                   case catch riak_get_subscription(LServer, Username, SRJID) of
-                       {ok, Subscription} ->
-                           Groups = case catch riak_get_roster_groups(LServer, Username, SRJID) of
-                                         {ok, JGrps} when is_list(JGrps) ->
-                                             lists:map(fun binary_to_list/1,
-                                                       JGrps);
-                                        _ ->
-                                            []
-                                    end,
-                           {Subscription, Groups};
-                       _ ->
-                           {none, []}
-                   end
-           end
-    end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-raw_to_record(LServer,
-              <<UsernameLen:16, Username:UsernameLen/binary,
-               SJIDLen:16, SJID:SJIDLen/binary,
-               NickLen:16, Nick:NickLen/binary,
-               SSubscription, SAsk,
-               SAskMessageLen:16, SAskMessage:SAskMessageLen/binary>>) ->
-    User = binary_to_list(Username),
-    case jlib:string_to_jid(binary_to_list(SJID)) of
-       error ->
-           error;
-       JID ->
-           LJID = jlib:jid_tolower(JID),
-           Subscription = case SSubscription of
-                              $B -> both;
-                              $T -> to;
-                              $F -> from;
-                              _ -> none
-                          end,
-           Ask = case SAsk of
-                     $S -> subscribe;
-                     $U -> unsubscribe;
-                     $B -> both;
-                     $O -> out;
-                     $I -> in;
-                     _ -> none
-                 end,
-           #roster{usj = {User, LServer, LJID},
-                   us = {User, LServer},
-                   jid = LJID,
-                   name = binary_to_list(Nick),
-                   subscription = Subscription,
-                   ask = Ask,
-                   askmessage = SAskMessage}
-    end.
-
-record_to_string(#roster{us = {User, _Server},
-                        jid = JID,
-                        name = Name,
-                        subscription = Subscription,
-                        ask = Ask,
-                        askmessage = AskMessage}) ->
-    Username = list_to_binary(User),
-    UsernameLen = size(Username),
-    SJID = list_to_binary(jlib:jid_to_string(jlib:jid_tolower(JID))),
-    SJIDLen = size(SJID),
-    Nick = list_to_binary(Name),
-    NickLen = size(Nick),
-    SSubscription = case Subscription of
-                       both -> $B;
-                       to   -> $T;
-                       from -> $F;
-                       none -> $N
-                   end,
-    SAsk = case Ask of
-              subscribe   -> $S;
-              unsubscribe -> $U;
-              both        -> $B;
-              out         -> $O;
-              in          -> $I;
-              none        -> $N
-          end,
-    SAskMessage = iolist_to_binary(AskMessage),
-    SAskMessageLen = size(SAskMessage),
-    <<UsernameLen:16, Username/binary,
-     SJIDLen:16, SJID/binary,
-     NickLen:16, Nick/binary,
-     SSubscription, SAsk,
-     SAskMessageLen:16, SAskMessage/binary>>.
-
-groups_to_binary(#roster{jid = JID, groups = Groups}) ->
-    SJID = list_to_binary(jlib:jid_to_string(jlib:jid_tolower(JID))),
-    SJIDLen = size(SJID),
-    %% Empty groups do not need to be converted to string to be inserted in
-    %% the database
-    lists:foldl(
-      fun([], Acc) ->
-              Acc;
-        (Group, Acc) ->
-             G = list_to_binary(Group),
-              Len = size(G),
-             <<Acc/binary, Len:16, G/binary>>
-      end, <<SJIDLen:16, SJID/binary>>, Groups).
-
-binary_to_groups(<<Len:16, SJID:Len/binary, Rest/binary>>) ->
-    {binary_to_list(SJID), binary_to_groups(Rest, [])}.
-
-binary_to_groups(<<Len:16, G:Len/binary, Rest/binary>>, Res) ->
-    binary_to_groups(Rest, [G | Res]);
-binary_to_groups(_, Res) ->
-    Res.
-
-
-webadmin_page(_, Host,
-             #request{us = _US,
-                      path = ["user", U, "roster"],
-                      q = Query,
-                      lang = Lang} = _Request) ->
-    Res = user_roster(U, Host, Query, Lang),
-    {stop, Res};
-
-webadmin_page(Acc, _, _) -> Acc.
-
-user_roster(User, Server, Query, Lang) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    US = {LUser, LServer},
-    Items1 = get_roster(LUser, LServer),
-    Res = user_roster_parse_query(User, Server, Items1, Query),
-    Items = get_roster(LUser, LServer),
-    SItems = lists:sort(Items),
-    FItems =
-       case SItems of
-           [] ->
-               [?CT("None")];
-           _ ->
-               [?XE("table",
-                    [?XE("thead",
-                         [?XE("tr",
-                              [?XCT("td", "Jabber ID"),
-                               ?XCT("td", "Nickname"),
-                               ?XCT("td", "Subscription"),
-                               ?XCT("td", "Pending"),
-                               ?XCT("td", "Groups")
-                              ])]),
-                     ?XE("tbody",
-                         lists:map(
-                           fun(R) ->
-                                   Groups =
-                                       lists:flatmap(
-                                         fun(Group) ->
-                                                 [?C(Group), ?BR]
-                                         end, R#roster.groups),
-                                   Pending = ask_to_pending(R#roster.ask),
-                                   TDJID = build_contact_jid_td(R#roster.jid),
-                                   ?XE("tr",
-                                       [TDJID,
-                                        ?XAC("td", [{"class", "valign"}],
-                                             R#roster.name),
-                                        ?XAC("td", [{"class", "valign"}],
-                                             atom_to_list(R#roster.subscription)),
-                                        ?XAC("td", [{"class", "valign"}],
-                                             atom_to_list(Pending)),
-                                        ?XAE("td", [{"class", "valign"}], Groups),
-                                        if
-                                            Pending == in ->
-                                                ?XAE("td", [{"class", "valign"}],
-                                                     [?INPUTT("submit",
-                                                              "validate" ++
-                                                              ejabberd_web_admin:term_to_id(R#roster.jid),
-                                                              "Validate")]);
-                                            true ->
-                                                ?X("td")
-                                        end,
-                                        ?XAE("td", [{"class", "valign"}],
-                                             [?INPUTT("submit",
-                                                      "remove" ++
-                                                      ejabberd_web_admin:term_to_id(R#roster.jid),
-                                                      "Remove")])])
-                           end, SItems))])]
-       end,
-    [?XC("h1", ?T("Roster of ") ++ us_to_list(US))] ++
-       case Res of
-           ok -> [?XREST("Submitted")];
-           error -> [?XREST("Bad format")];
-           nothing -> []
-       end ++
-       [?XAE("form", [{"action", ""}, {"method", "post"}],
-             FItems ++
-             [?P,
-              ?INPUT("text", "newjid", ""), ?C(" "),
-              ?INPUTT("submit", "addjid", "Add Jabber ID")
-             ])].
-
-build_contact_jid_td(RosterJID) ->
-    %% Convert {U, S, R} into {jid, U, S, R, U, S, R}:
-    ContactJID = jlib:make_jid(RosterJID),
-    JIDURI = case {ContactJID#jid.luser, ContactJID#jid.lserver} of
-                {"", _} -> "";
-                {CUser, CServer} ->
-                    case lists:member(CServer, ?MYHOSTS) of
-                        false -> "";
-                        true -> "/admin/server/" ++ CServer ++ "/user/" ++ CUser ++ "/"
-                    end
-            end,
-    case JIDURI of
-       [] ->
-           ?XAC("td", [{"class", "valign"}], jlib:jid_to_string(RosterJID));
-       URI when is_list(URI) ->
-           ?XAE("td", [{"class", "valign"}], [?AC(JIDURI, jlib:jid_to_string(RosterJID))])
-    end.
-
-user_roster_parse_query(User, Server, Items, Query) ->
-    case lists:keysearch("addjid", 1, Query) of
-       {value, _} ->
-           case lists:keysearch("newjid", 1, Query) of
-               {value, {_, undefined}} ->
-                   error;
-               {value, {_, SJID}} ->
-                   case jlib:string_to_jid(SJID) of
-                       JID when is_record(JID, jid) ->
-                           user_roster_subscribe_jid(User, Server, JID),
-                           ok;
-                       error ->
-                           error
-                   end;
-               false ->
-                   error
-           end;
-       false ->
-           case catch user_roster_item_parse_query(
-                        User, Server, Items, Query) of
-               submitted ->
-                   ok;
-               {'EXIT', _Reason} ->
-                   error;
-               _ ->
-                   nothing
-           end
-    end.
-
-
-user_roster_subscribe_jid(User, Server, JID) ->
-    out_subscription(User, Server, JID, subscribe),
-    UJID = jlib:make_jid(User, Server, ""),
-    ejabberd_router:route(
-      UJID, JID, {xmlelement, "presence", [{"type", "subscribe"}], []}).
-
-user_roster_item_parse_query(User, Server, Items, Query) ->
-    lists:foreach(
-      fun(R) ->
-             JID = R#roster.jid,
-             case lists:keysearch(
-                    "validate" ++ ejabberd_web_admin:term_to_id(JID), 1, Query) of
-                 {value, _} ->
-                     JID1 = jlib:make_jid(JID),
-                     out_subscription(
-                       User, Server, JID1, subscribed),
-                     UJID = jlib:make_jid(User, Server, ""),
-                     ejabberd_router:route(
-                       UJID, JID1, {xmlelement, "presence",
-                                    [{"type", "subscribed"}], []}),
-                     throw(submitted);
-                 false ->
-                     case lists:keysearch(
-                            "remove" ++ ejabberd_web_admin:term_to_id(JID), 1, Query) of
-                         {value, _} ->
-                             UJID = jlib:make_jid(User, Server, ""),
-                             process_iq(
-                               UJID, UJID,
-                               #iq{type = set,
-                                   sub_el = {xmlelement, "query",
-                                             [{"xmlns", ?NS_ROSTER}],
-                                             [{xmlelement, "item",
-                                               [{"jid", jlib:jid_to_string(JID)},
-                                                {"subscription", "remove"}],
-                                               []}]}}),
-                             throw(submitted);
-                         false ->
-                             ok
-                     end
-
-             end
-      end, Items),
-    nothing.
-
-us_to_list({User, Server}) ->
-    jlib:jid_to_string({User, Server, ""}).
-
-webadmin_user(Acc, _User, _Server, Lang) ->
-    Acc ++ [?XE("h3", [?ACT("roster/", "Roster")])].
-
-
-riak_get_roster(LServer, Username) ->
-    ejabberd_riak:get_by_index(
-      LServer, <<"roster">>, <<"user_bin">>, Username).
-
-riak_get_roster_jid_groups(LServer, Username) ->
-    case ejabberd_riak:get_by_index(
-           LServer, <<"roster_groups">>, <<"user_bin">>, Username) of
-        {ok, JGs} ->
-            Res = lists:map(fun binary_to_groups/1, JGs),
-            {ok, Res};
-        Error -> Error
-    end.
-
-riak_get_roster_groups(LServer, Username, SJID) ->
-    Key = <<Username/binary, $/, SJID/binary>>,
-    case ejabberd_riak:get(LServer, <<"roster_groups">>, Key) of
-        {ok, Gs} ->
-            {_, Res} = binary_to_groups(Gs),
-            {ok, Res};
-        {error, notfound} ->
-            {ok, []};
-        Error -> Error
-    end.
-
-riak_get_roster_by_jid(LServer, Username, SJID) ->
-    Key = <<Username/binary, $/, SJID/binary>>,
-    ejabberd_riak:get(LServer, <<"roster">>, Key).
-
-riak_del_roster(LServer, Username, SJID) ->
-    Key = <<Username/binary, $/, SJID/binary>>,
-    ejabberd_riak:delete(LServer, <<"roster">>, Key).
-
-riak_update_roster(LServer, Username, SJID, ItemVals, ItemGroups) ->
-    Key = <<Username/binary, $/, SJID/binary>>,
-    ejabberd_riak:put(
-      LServer, <<"roster">>, Key, ItemVals,
-      [{<<"user_bin">>, Username}]),
-    ejabberd_riak:put(
-      LServer, <<"roster_groups">>, Key, ItemGroups,
-      [{<<"user_bin">>, Username}]).
-
-riak_roster_subscribe(LServer, Username, SJID, ItemVals) ->
-    Key = <<Username/binary, $/, SJID/binary>>,
-    ejabberd_riak:put(
-      LServer, <<"roster">>, Key, ItemVals,
-      [{<<"user_bin">>, Username}]).
-
-riak_get_subscription(LServer, Username, SJID) ->
-    case riak_get_roster_by_jid(LServer, Username, SJID) of
-        {ok, SR} ->
-            case raw_to_record(LServer, SR) of
-                error ->
-                    {error, bad_record};
-                R ->
-                    {ok, R#roster.subscription}
-            end;
-        Error ->
-            Error
-    end.
-
-riak_set_roster_version(LServer, Username, RosterVersion) ->
-    ejabberd_riak:put(LServer, <<"roster_version">>,
-                      Username, list_to_binary(RosterVersion)).
-
-
-riak_del_user_roster(LServer, Username) ->
-    case ejabberd_riak:get_keys_by_index(
-           LServer, <<"roster">>, <<"user_bin">>, Username) of
-        {ok, Keys} ->
-            lists:foreach(
-              fun(Key) ->
-                      ejabberd_riak:delete(LServer, <<"roster">>, Key)
-              end, Keys);
-        _ ->
-            ok
-    end,
-    case ejabberd_riak:get_keys_by_index(
-           LServer, <<"roster_groups">>, <<"user_bin">>, Username) of
-        {ok, GKeys} ->
-            lists:foreach(
-              fun(Key) ->
-                      ejabberd_riak:delete(LServer, <<"roster_groups">>, Key)
-              end, GKeys);
-        _ ->
-            ok
-    end,
-    ejabberd_riak:delete(LServer, <<"roster_version">>, Username).
-
index c98750ed002bbfdfe75878ae432798ab1373e0ca..e7dd77224a5ffad82d28a14ca7ddba5bc23d8123 100644 (file)
@@ -212,6 +212,19 @@ get_vcard(LUser, LServer, odbc) ->
          end;
       {selected, [<<"vcard">>], []} -> [];
       _ -> error
+    end;
+get_vcard(LUser, LServer, riak) ->
+    Username = LUser,
+    case catch ejabberd_riak:get(LServer, <<"vcard">>, Username) of
+        {ok, SVCARD} ->
+            case xml_stream:parse_element(SVCARD) of
+                {error, _Reason} -> error;
+                VCARD -> [VCARD]
+            end;
+        {error, notfound} ->
+            [];
+        _ ->
+            error
     end.
 
 set_vcard(User, LServer, VCARD) ->
@@ -322,7 +335,25 @@ set_vcard(User, LServer, VCARD) ->
                                        SLGiven, SLLocality, SLMiddle,
                                        SLNickname, SLOrgName, SLOrgUnit,
                                        SLocality, SMiddle, SNickname, SOrgName,
-                                       SOrgUnit, SVCARD, Username)
+                                       SOrgUnit, SVCARD, Username);
+            riak ->
+                   Username = LUser,
+                   SVCARD = xml:element_to_binary(VCARD),
+
+                   ejabberd_riak:put(
+                     LServer, <<"vcard">>, Username, SVCARD,
+                     [{<<"bday_bin">>, LBDay},
+                      {<<"ctry_bin">>, LCTRY},
+                      {<<"email_bin">>, LEMail},
+                      {<<"fn_bin">>, LFN},
+                      {<<"family_bin">>, LFamily},
+                      {<<"given_bin">>, LGiven},
+                      {<<"locality_bin">>, LLocality},
+                      {<<"middle_bin">>, LMiddle},
+                      {<<"nickname_bin">>, LNickname},
+                      {<<"orgname_bin">>, LOrgName},
+                      {<<"orgunit_bin">>, LOrgUnit},
+                      {<<"user_bin">>, Username}])
           end,
           ejabberd_hooks:run(vcard_set, LServer,
                              [LUser, LServer, VCARD])
@@ -687,14 +718,18 @@ search(LServer, MatchSpec, AllowReturnAll, odbc) ->
                 Rs;
             Error -> ?ERROR_MSG("~p", [Error]), []
           end
-    end.
+    end;
+search(_LServer, _MatchSpec, _AllowReturnAll, riak) ->
+    [].
 
 make_matchspec(LServer, Data, mnesia) ->
     GlobMatch = #vcard_search{_ = '_'},
     Match = filter_fields(Data, GlobMatch, LServer, mnesia),
     Match;
 make_matchspec(LServer, Data, odbc) ->
-    filter_fields(Data, <<"">>, LServer, odbc).
+    filter_fields(Data, <<"">>, LServer, odbc);
+make_matchspec(_LServer, _Data, riak) ->
+    [].
 
 filter_fields([], Match, _LServer, mnesia) -> Match;
 filter_fields([], Match, _LServer, odbc) ->
@@ -884,7 +919,11 @@ remove_user(LUser, LServer, odbc) ->
                                  [[<<"delete from vcard where username='">>,
                                    Username, <<"';">>],
                                   [<<"delete from vcard_search where lusername='">>,
-                                   Username, <<"';">>]]).
+                                   Username, <<"';">>]]);
+remove_user(LUser, LServer, riak) ->
+    Username = LUser,
+    ejabberd_riak:delete(LServer, <<"vcard">>, Username),
+    ok.
 
 update_tables() ->
     update_vcard_table(),
diff --git a/src/mod_vcard_riak.erl b/src/mod_vcard_riak.erl
deleted file mode 100644 (file)
index 44ce35f..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File    : mod_vcard_riak.erl
-%%% Author  : Alexey Shchepin <alexey@process-one.net>
-%%% Purpose : vCard support via Riak
-%%% Created :  6 Jan 2012 by Alexey Shchepin <alexey@process-one.net>
-%%%
-%%%
-%%% ejabberd, Copyright (C) 2002-2011   ProcessOne
-%%%
-%%% This program is free software; you can redistribute it and/or
-%%% modify it under the terms of the GNU General Public License as
-%%% published by the Free Software Foundation; either version 2 of the
-%%% License, or (at your option) any later version.
-%%%
-%%% This program is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-%%% General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License
-%%% along with this program; if not, write to the Free Software
-%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-%%% 02111-1307 USA
-%%%
-%%%----------------------------------------------------------------------
-
--module(mod_vcard_riak).
--author('alexey@process-one.net').
-
--behaviour(gen_mod).
-
--export([start/2, stop/1,
-        get_sm_features/5,
-        process_local_iq/3,
-        process_sm_iq/3,
-        remove_user/2]).
-
--include("ejabberd.hrl").
--include("jlib.hrl").
-
-
--define(JUD_MATCHES, 30).
--define(PROCNAME, ejabberd_mod_vcard).
-
-start(Host, Opts) ->
-    ejabberd_hooks:add(remove_user, Host,
-                      ?MODULE, remove_user, 50),
-    IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
-    gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
-                                 ?MODULE, process_local_iq, IQDisc),
-    gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_VCARD,
-                                 ?MODULE, process_sm_iq, IQDisc),
-    ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
-    ok.
-
-stop(Host) ->
-    ejabberd_hooks:delete(remove_user, Host,
-                         ?MODULE, remove_user, 50),
-    gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
-    gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD),
-    ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
-    ok.
-
-get_sm_features({error, _Error} = Acc, _From, _To, _Node, _Lang) ->
-    Acc;
-
-get_sm_features(Acc, _From, _To, Node, _Lang) ->
-    case Node of
-       [] ->
-           case Acc of
-               {result, Features} ->
-                   {result, [?NS_VCARD | Features]};
-               empty ->
-                   {result, [?NS_VCARD]}
-           end;
-       _ ->
-           Acc
-     end.
-
-process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
-    case Type of
-       set ->
-           IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
-       get ->
-           IQ#iq{type = result,
-                 sub_el = [{xmlelement, "vCard",
-                            [{"xmlns", ?NS_VCARD}],
-                            [{xmlelement, "FN", [],
-                              [{xmlcdata, "ejabberd"}]},
-                             {xmlelement, "URL", [],
-                              [{xmlcdata, ?EJABBERD_URI}]},
-                             {xmlelement, "DESC", [],
-                              [{xmlcdata,
-                                translate:translate(
-                                  Lang,
-                                  "Erlang Jabber Server") ++
-                                  "\nCopyright (c) 2002-2011 ProcessOne"}]},
-                             {xmlelement, "BDAY", [],
-                              [{xmlcdata, "2002-11-16"}]}
-                            ]}]}
-    end.
-
-
-process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
-    case Type of
-       set ->
-           #jid{user = User, lserver = LServer} = From,
-           case lists:member(LServer, ?MYHOSTS) of
-               true ->
-                   set_vcard(User, LServer, SubEl),
-                   IQ#iq{type = result, sub_el = []};
-               false ->
-                   IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
-           end;
-       get ->
-           #jid{luser = LUser, lserver = LServer} = To,
-            Username = list_to_binary(LUser),
-           case catch ejabberd_riak:get(LServer, <<"vcard">>, Username) of
-               {ok, SVCARD} ->
-                   case xml_stream:parse_element(SVCARD) of
-                       {error, _Reason} ->
-                           IQ#iq{type = error,
-                                 sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
-                       VCARD ->
-                           IQ#iq{type = result, sub_el = [VCARD]}
-                   end;
-               {error, notfound} ->
-                   IQ#iq{type = result, sub_el = []};
-               _ ->
-                   IQ#iq{type = error,
-                         sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}
-           end
-    end.
-
-set_vcard(User, LServer, VCARD) ->
-    FN       = xml:get_path_s(VCARD, [{elem, "FN"},                     cdata]),
-    Family   = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "FAMILY"},    cdata]),
-    Given    = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "GIVEN"},     cdata]),
-    Middle   = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "MIDDLE"},    cdata]),
-    Nickname = xml:get_path_s(VCARD, [{elem, "NICKNAME"},               cdata]),
-    BDay     = xml:get_path_s(VCARD, [{elem, "BDAY"},                   cdata]),
-    CTRY     = xml:get_path_s(VCARD, [{elem, "ADR"}, {elem, "CTRY"},    cdata]),
-    Locality = xml:get_path_s(VCARD, [{elem, "ADR"}, {elem, "LOCALITY"},cdata]),
-    EMail1   = xml:get_path_s(VCARD, [{elem, "EMAIL"}, {elem, "USERID"},cdata]),
-    EMail2   = xml:get_path_s(VCARD, [{elem, "EMAIL"},                  cdata]),
-    OrgName  = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGNAME"}, cdata]),
-    OrgUnit  = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]),
-    EMail = case EMail1 of
-               "" ->
-                   EMail2;
-               _ ->
-                   EMail1
-           end,
-
-    LUser     = jlib:nodeprep(User),
-    LFN       = stringprep:tolower(FN),
-    LFamily   = stringprep:tolower(Family),
-    LGiven    = stringprep:tolower(Given),
-    LMiddle   = stringprep:tolower(Middle),
-    LNickname = stringprep:tolower(Nickname),
-    LBDay     = stringprep:tolower(BDay),
-    LCTRY     = stringprep:tolower(CTRY),
-    LLocality = stringprep:tolower(Locality),
-    LEMail    = stringprep:tolower(EMail),
-    LOrgName  = stringprep:tolower(OrgName),
-    LOrgUnit  = stringprep:tolower(OrgUnit),
-
-    if
-       (LUser     == error) or
-       (LFN       == error) or
-       (LFamily   == error) or
-       (LGiven    == error) or
-       (LMiddle   == error) or
-       (LNickname == error) or
-       (LBDay     == error) or
-       (LCTRY     == error) or
-       (LLocality == error) or
-       (LEMail    == error) or
-       (LOrgName  == error) or
-       (LOrgUnit  == error) ->
-           {error, badarg};
-       true ->
-            Username = list_to_binary(LUser),
-           SVCARD = xml:element_to_binary(VCARD),
-
-            ejabberd_riak:put(
-              LServer, <<"vcard">>, Username, SVCARD,
-              [{<<"bday_bin">>, list_to_binary(LBDay)},
-               {<<"ctry_bin">>, list_to_binary(LCTRY)},
-               {<<"email_bin">>, list_to_binary(LEMail)},
-               {<<"fn_bin">>, list_to_binary(LFN)},
-               {<<"family_bin">>, list_to_binary(LFamily)},
-               {<<"given_bin">>, list_to_binary(LGiven)},
-               {<<"locality_bin">>, list_to_binary(LLocality)},
-               {<<"middle_bin">>, list_to_binary(LMiddle)},
-               {<<"nickname_bin">>, list_to_binary(LNickname)},
-               {<<"orgname_bin">>, list_to_binary(LOrgName)},
-               {<<"orgunit_bin">>, list_to_binary(LOrgUnit)},
-               {<<"user_bin">>, Username}]),
-
-           ejabberd_hooks:run(vcard_set, LServer, [LUser, LServer, VCARD])
-    end.
-
-remove_user(User, Server) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Username = list_to_binary(LUser),
-    ejabberd_riak:delete(LServer, <<"vcard">>, Username),
-    ok.