]> granicus.if.org Git - ejabberd/commitdiff
Rewrite several modules to use XML generator
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Fri, 29 Jul 2016 10:21:00 +0000 (13:21 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Fri, 29 Jul 2016 10:21:00 +0000 (13:21 +0300)
src/ejabberd_xmlrpc.erl
src/mod_admin_extra.erl
src/mod_http_api.erl
src/mod_http_fileserver.erl
src/mod_metrics.erl
src/mod_pres_counter.erl
src/mod_private.erl
src/mod_proxy65_service.erl
src/mod_proxy65_sm.erl
src/mod_service_log.erl
src/mod_vcard.erl

index 6680451e46e5fda2a49c831544ff1ddbee23ee18..6259b4efd8453e20dc76740abd34dea6c12afe41 100644 (file)
@@ -42,7 +42,7 @@
 -include("ejabberd_http.hrl").
 -include("mod_roster.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -record(state,
        {access_commands = [] :: list(),
index 8f6724281030306f1f6ca8a943bce08282ee0aff..a147a58818ad20185a8ac284a7e8783aa40af467 100644 (file)
@@ -54,7 +54,7 @@
 -include("ejabberd_commands.hrl").
 -include("mod_roster.hrl").
 -include("ejabberd_sm.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 %%%
 %%% gen_mod
@@ -879,20 +879,22 @@ set_presence(User, Host, Resource, Type, Show, Status, Priority)
         when is_integer(Priority) ->
     BPriority = integer_to_binary(Priority),
     set_presence(User, Host, Resource, Type, Show, Status, BPriority);
-set_presence(User, Host, Resource, Type, Show, Status, Priority) ->
+set_presence(User, Host, Resource, Type, Show, Status, Priority0) ->
+    Priority = if is_integer(Priority0) -> Priority0;
+                 true -> binary_to_integer(Priority0)
+              end,
     case ejabberd_sm:get_session_pid(User, Host, Resource) of
        none ->
            error;
        Pid ->
-           USR = jid:to_string(jid:make(User, Host, Resource)),
-           US = jid:to_string(jid:make(User, Host, <<>>)),
-           Message = {route_xmlstreamelement,
-                   {xmlel, <<"presence">>,
-                       [{<<"from">>, USR}, {<<"to">>, US}, {<<"type">>, Type}],
-                       [{xmlel, <<"show">>, [], [{xmlcdata, Show}]},
-                       {xmlel, <<"status">>, [], [{xmlcdata, Status}]},
-                       {xmlel, <<"priority">>, [], [{xmlcdata, Priority}]}]}},
-           Pid ! Message,
+           From = jid:make(User, Host, Resource),
+           To = jid:make(User, Host),
+           Presence = #presence{from = From, to = To,
+                                type = jlib:binary_to_atom(Type),
+                                show = jlib:binary_to_atom(Show),
+                                status = xmpp:mk_text(Status),
+                                priority = Priority},
+           Pid ! {route, From, To, Presence},
            ok
     end.
 
@@ -930,20 +932,12 @@ user_sessions_info(User, Host) ->
 %%%
 
 set_nickname(User, Host, Nickname) ->
-    R = mod_vcard:process_sm_iq(
-         {jid, User, Host, <<>>, User, Host, <<>>},
-         {jid, User, Host, <<>>, User, Host, <<>>},
-         {iq, <<>>, set, <<>>, <<"en">>,
-          {xmlel, <<"vCard">>, [
-            {<<"xmlns">>, <<"vcard-temp">>}], [
-               {xmlel, <<"NICKNAME">>, [], [{xmlcdata, Nickname}]}
-            ]
-         }}),
-    case R of
-       {iq, <<>>, result, <<>>, _L, []} ->
-           ok;
-       _ ->
-           error
+    VCard = xmpp:encode(#vcard_temp{nickname = Nickname}),
+    case mod_vcard:set_vcard(User, jid:nameprep(Host), VCard) of
+       {error, badarg} ->
+           error;
+       ok ->
+           ok
     end.
 
 get_vcard(User, Host, Name) ->
@@ -967,26 +961,17 @@ set_vcard(User, Host, Name, Subname, SomeContent) ->
 %%
 %% Internal vcard
 
-get_module_resource(Server) ->
-    case gen_mod:get_module_opt(Server, ?MODULE, module_resource, fun(A) -> A end, none) of
-       none -> list_to_binary(atom_to_list(?MODULE));
-       R when is_binary(R) -> R
-    end.
-
 get_vcard_content(User, Server, Data) ->
-    [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}),
-    JID = jid:make(User, Server, get_module_resource(Server)),
-    IQ = #iq{type = get, xmlns = ?NS_VCARD},
-    IQr = Module:Function(JID, JID, IQ),
-    [A1] = IQr#iq.sub_el,
-    case A1#xmlel.children of
-       [_|_] ->
-           case get_vcard(Data, A1) of
+    case mod_vcard:get_vcard(jid:nodeprep(User), jid:nameprep(Server)) of
+       [_|_] = Els ->
+           case get_vcard(Data, Els) of
                [false] -> throw(error_no_value_found_in_vcard);
                ElemList -> ?DEBUG("ELS ~p", [ElemList]), [fxml:get_tag_cdata(Elem) || Elem <- ElemList]
            end;
        [] ->
-           throw(error_no_vcard_found)
+           throw(error_no_vcard_found);
+       error ->
+           throw(database_failure)
     end.
 
 get_vcard([<<"TEL">>, TelType], {_, _, _, OldEls}) ->
@@ -1011,25 +996,19 @@ set_vcard_content(User, Server, Data, SomeContent) ->
        [Bin | _] when is_binary(Bin) -> SomeContent;
        Bin when is_binary(Bin) -> [SomeContent]
     end,
-    [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}),
-    JID = jid:make(User, Server, get_module_resource(Server)),
-    IQ = #iq{type = get, xmlns = ?NS_VCARD},
-    IQr = Module:Function(JID, JID, IQ),
-
     %% Get old vcard
-    A4 = case IQr#iq.sub_el of
+    A4 = case mod_vcard:get_vcard(jid:nodeprep(User), jid:nameprep(Server)) of
             [A1] ->
                 {_, _, _, A2} = A1,
                 update_vcard_els(Data, ContentList, A2);
             [] ->
-                update_vcard_els(Data, ContentList, [])
+                update_vcard_els(Data, ContentList, []);
+            error ->
+                throw(database_failure)
         end,
-
     %% Build new vcard
     SubEl = {xmlel, <<"vCard">>, [{<<"xmlns">>,<<"vcard-temp">>}], A4},
-    IQ2 = #iq{type=set, sub_el = SubEl},
-
-    Module:Function(JID, JID, IQ2),
+    mod_vcard:set_vcard(User, jid:nameprep(Server), SubEl),
     ok.
 
 take_vcard_tel(TelType, [{xmlel, <<"TEL">>, _, SubEls}=OldEl | OldEls], NewEls, Taken) ->
@@ -1090,11 +1069,7 @@ add_rosteritem(LU, LS, User, Server, Nick, Group, Subscription, Xattrs) ->
 
 subscribe(LU, LS, User, Server, Nick, Group, Subscription, _Xattrs) ->
     ItemEl = build_roster_item(User, Server, {add, Nick, Subscription, Group}),
-    mod_roster:set_items(
-       LU, LS,
-       {xmlel, <<"query">>,
-            [{<<"xmlns">>, ?NS_ROSTER}],
-            [ItemEl]}).
+    mod_roster:set_items(LU, LS, #roster_query{items = [ItemEl]}).
 
 delete_rosteritem(LocalUser, LocalServer, User, Server) ->
     case unsubscribe(LocalUser, LocalServer, User, Server) of
@@ -1107,11 +1082,7 @@ delete_rosteritem(LocalUser, LocalServer, User, Server) ->
 
 unsubscribe(LU, LS, User, Server) ->
     ItemEl = build_roster_item(User, Server, remove),
-    mod_roster:set_items(
-       LU, LS,
-       {xmlel, <<"query">>,
-            [{<<"xmlns">>, ?NS_ROSTER}],
-            [ItemEl]}).
+    mod_roster:set_items(LU, LS, #roster_query{items = [ItemEl]}).
 
 %% -----------------------------
 %% Get Roster
@@ -1201,28 +1172,16 @@ push_roster_item(LU, LS, R, U, S, Action) ->
     ejabberd_router:route(jid:remove_resource(LJID), LJID, ResIQ).
 
 build_roster_item(U, S, {add, Nick, Subs, Group}) ->
-    {xmlel, <<"item">>,
-     [{<<"jid">>, jid:to_string(jid:make(U, S, <<>>))},
-      {<<"name">>, Nick},
-      {<<"subscription">>, Subs}],
-     [{xmlel, <<"group">>, [], [{xmlcdata, Group}]}]
-    };
+    #roster_item{jid = jid:make(U, S),
+                name = Nick,
+                subscription = jlib:binary_to_atom(Subs),
+                groups = [Group]};
 build_roster_item(U, S, remove) ->
-    {xmlel, <<"item">>,
-     [{<<"jid">>, jid:to_string(jid:make(U, S, <<>>))},
-      {<<"subscription">>, <<"remove">>}],
-     []
-    }.
+    #roster_item{jid = jid:make(U, S), subscription = remove}.
 
 build_iq_roster_push(Item) ->
-    {xmlel, <<"iq">>,
-     [{<<"type">>, <<"set">>}, {<<"id">>, <<"push">>}],
-     [{xmlel, <<"query">>,
-       [{<<"xmlns">>, ?NS_ROSTER}],
-       [Item]
-      }
-     ]
-    }.
+    #iq{type = set, id = <<"push">>,
+       sub_els = [#roster_query{items = [Item]}]}.
 
 build_broadcast(U, S, {add, _Nick, Subs, _Group}) ->
     build_broadcast(U, S, list_to_atom(binary_to_list(Subs)));
@@ -1268,17 +1227,9 @@ get_last(User, Server) ->
 %% <aa xmlns='bb'>Cluth</aa>
 
 private_get(Username, Host, Element, Ns) ->
-    From = jid:make(Username, Host, <<>>),
-    To = jid:make(Username, Host, <<>>),
-    IQ = {iq, <<>>, get, ?NS_PRIVATE, <<>>,
-         {xmlel, <<"query">>,
-          [{<<"xmlns">>,?NS_PRIVATE}],
-          [{xmlel, Element, [{<<"xmlns">>, Ns}], []}]}},
-    ResIq = mod_private:process_sm_iq(From, To, IQ),
-    [{xmlel, <<"query">>,
-      [{<<"xmlns">>, ?NS_PRIVATE}],
-      [SubEl]}] = ResIq#iq.sub_el,
-    binary_to_list(fxml:element_to_binary(SubEl)).
+    Els = mod_private:get_data(jid:nodeprep(Username), jid:nameprep(Host),
+                              [Ns, Element]),
+    binary_to_list(fxml:element_to_binary(xmpp:encode(#private{xml_els = Els}))).
 
 private_set(Username, Host, ElementString) ->
     case fxml_stream:parse_element(ElementString) of
@@ -1291,13 +1242,9 @@ private_set(Username, Host, ElementString) ->
     end.
 
 private_set2(Username, Host, Xml) ->
-    From = jid:make(Username, Host, <<>>),
-    To = jid:make(Username, Host, <<>>),
-    IQ = {iq, <<>>, set, ?NS_PRIVATE, <<>>,
-         {xmlel, <<"query">>,
-          [{<<"xmlns">>, ?NS_PRIVATE}],
-          [Xml]}},
-    mod_private:process_sm_iq(From, To, IQ),
+    NS = fxml:get_tag_attr_s(<<"xmlns">>, Xml),
+    mod_private:set_data(jid:nodeprep(Username), jid:nameprep(Host),
+                        [{NS, Xml}]),
     ok.
 
 %%%
@@ -1395,23 +1342,25 @@ send_packet_all_resources(FromJID, ToU, ToS, ToR, Packet) ->
     ejabberd_router:route(FromJID, ToJID, Packet).
 
 build_packet(Type, Subject, Body) ->
-    Tail = if Subject == <<"">>; Type == <<"chat">> -> [];
-             true -> [{xmlel, <<"subject">>, [], [{xmlcdata, Subject}]}]
-          end,
-    {xmlel, <<"message">>,
-     [{<<"type">>, Type}, {<<"id">>, randoms:get_string()}],
-     [{xmlel, <<"body">>, [], [{xmlcdata, Body}]} | Tail]
-    }.
+    #message{type = jlib:binary_to_atom(Type),
+            body = xmpp:mk_text(Body),
+            subject = xmpp:mk_text(Subject)}.
 
 send_stanza(FromString, ToString, Stanza) ->
-    case fxml_stream:parse_element(Stanza) of
-       {error, Error} ->
-           {error, Error};
-       XmlEl ->
-           #xmlel{attrs = Attrs} = XmlEl,
-           From = jid:from_string(proplists:get_value(<<"from">>, Attrs, FromString)),
-           To = jid:from_string(proplists:get_value(<<"to">>, Attrs, ToString)),
-           ejabberd_router:route(From, To, XmlEl)
+    try
+       #xmlel{} = El = fxml_stream:parse_element(Stanza),
+       #jid{} = From = jid:from_string(FromString),
+       #jid{} = To = jid:to_string(ToString),
+       Pkt = xmpp:decode(El, [ignore_els]),
+       ejabberd_router:route(From, To, Pkt)
+    catch _:{xmpp_codec, Why} ->
+           io:format("incorrect stanza: ~s~n", [xmpp:format_error(Why)]),
+           {error, Why};
+         _:{badmatch, {error, Why}} ->
+           io:format("invalid xml: ~p~n", [Why]),
+           {error, Why};
+         _:{badmatch, error} ->
+           {error, "JID malformed"}
     end.
 
 send_stanza_c2s(Username, Host, Resource, Stanza) ->
@@ -1427,17 +1376,15 @@ send_stanza_c2s(Username, Host, Resource, Stanza) ->
     end.
 
 privacy_set(Username, Host, QueryS) ->
-    From = jid:make(Username, Host, <<"">>),
-    To = jid:make(<<"">>, Host, <<"">>),
+    From = jid:make(Username, Host),
+    To = jid:make(Host),
     QueryEl = fxml_stream:parse_element(QueryS),
-    StanzaEl = {xmlel, <<"iq">>, [{<<"type">>, <<"set">>}], [QueryEl]},
-    IQ = jlib:iq_query_info(StanzaEl),
-    ejabberd_hooks:run_fold(
-                    privacy_iq_set,
-                    Host,
-                    {error, ?ERR_FEATURE_NOT_IMPLEMENTED},
-                    [From, To, IQ]
-                   ),
+    SubEl = xmpp:decode(QueryEl),
+    IQ = #iq{type = set, id = <<"push">>, sub_els = [SubEl]},
+    ejabberd_hooks:run_fold(privacy_iq_set,
+                           Host,
+                           {error, xmpp:err_feature_not_implemented()},
+                           [From, To, IQ]),
     ok.
 
 %%%
@@ -1618,5 +1565,4 @@ is_glob_match(String, <<"!", Glob/binary>>) ->
 is_glob_match(String, Glob) ->
     is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
 
-mod_opt_type(module_resource) -> fun (A) -> A end;
-mod_opt_type(_) -> [module_resource].
+mod_opt_type(_) -> [].
index 815ed3ab6103220118860e8e1d0eb7cacbd58cfd..f3a69aa800ae1165cb9344a9471881767255ab6f 100644 (file)
@@ -77,7 +77,7 @@
 -export([start/2, stop/1, process/2, mod_opt_type/1, depends/2]).
 
 -include("ejabberd.hrl").
--include("jlib.hrl").
+-include("xmpp.hrl").
 -include("logger.hrl").
 -include("ejabberd_http.hrl").
 
index 37e02edd85b55d3208717f683539ffb6355b8e92..728a2d137632e2b734e99cbdfc0f7d405939e668 100644 (file)
@@ -51,9 +51,6 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 -include("ejabberd_http.hrl").
-
--include("jlib.hrl").
-
 -include_lib("kernel/include/file.hrl").
 
 -record(state,
index f1d487e0e1148d6878138c6c2f6de08220d1f97a..cb7946a2858455e144c6ae5172ac81efd591229f 100644 (file)
@@ -31,7 +31,7 @@
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
--include("jlib.hrl").
+-include("jid.hrl").
 
 -define(HOOKS, [offline_message_hook,
                 sm_register_connection_hook, sm_remove_connection_hook,
index e6f2cfbabd61981371d5a356e5ca5e958066f52e..786ba97f28da05fccf2eac5b2f23a9f673abc978 100644 (file)
@@ -33,7 +33,7 @@
 -include("ejabberd.hrl").
 -include("logger.hrl").
 
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -record(pres_counter,
        {dir, start, count, logged = false}).
@@ -52,27 +52,24 @@ depends(_Host, _Opts) ->
     [].
 
 check_packet(_, _User, Server, _PrivacyList,
-            {From, To, #xmlel{name = Name, attrs = Attrs}}, Dir) ->
-    case Name of
-      <<"presence">> ->
-         IsSubscription = case fxml:get_attr_s(<<"type">>, Attrs)
-                              of
-                            <<"subscribe">> -> true;
-                            <<"subscribed">> -> true;
-                            <<"unsubscribe">> -> true;
-                            <<"unsubscribed">> -> true;
-                            _ -> false
-                          end,
-         if IsSubscription ->
-                JID = case Dir of
-                        in -> To;
-                        out -> From
-                      end,
-                update(Server, JID, Dir);
-            true -> allow
-         end;
-      _ -> allow
-    end.
+            {From, To, #presence{type = Type}}, Dir) ->
+    IsSubscription = case Type of
+                        subscribe -> true;
+                        subscribed -> true;
+                        unsubscribe -> true;
+                        unsubscribed -> true;
+                        _ -> false
+                    end,
+    if IsSubscription ->
+           JID = case Dir of
+                     in -> To;
+                     out -> From
+                 end,
+           update(Server, JID, Dir);
+       true -> allow
+    end;
+check_packet(_, _User, _Server, _PrivacyList, _Pkt, _Dir) ->
+    allow.
 
 update(Server, JID, Dir) ->
     StormCount = gen_mod:get_module_opt(Server, ?MODULE, count,
index e6d0fd7cde0a3d807ef16c0dd72efdff303e7260..6236b10123054ce8050bfab25afa8e15bcfda4c5 100644 (file)
@@ -32,7 +32,7 @@
 -behaviour(gen_mod).
 
 -export([start/2, stop/1, process_sm_iq/1, import/3,
-        remove_user/2, get_data/2, export/1, import/1,
+        remove_user/2, get_data/2, get_data/3, export/1, import/1,
         mod_opt_type/1, set_data/3, depends/2]).
 
 -include("ejabberd.hrl").
index 7db6f9da2a9ee76fb301c35ecd6d7b5abcf72f7f..e90ff21bdadf0a0ccbeea63851e31773b5cc0a76 100644 (file)
 -export([init/1, handle_info/2, handle_call/3,
         handle_cast/2, terminate/2, code_change/3]).
 
--export([start_link/2, add_listener/2,
+-export([start_link/2, add_listener/2, process_disco_info/1,
+        process_disco_items/1, process_vcard/1, process_bytestreams/1,
         transform_module_options/1, delete_listener/1]).
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
-
--include("jlib.hrl").
+-include("xmpp.hrl").
 
 -define(PROCNAME, ejabberd_mod_proxy65_service).
 
--record(state,
-       {myhost = <<"">>     :: binary(),
-         serverhost = <<"">> :: binary(),
-         name = <<"">>       :: binary(),
-         stream_addr = []    :: [attr()],
-         port = 0            :: inet:port_number(),
-         ip = {127,0,0,1}    :: inet:ip_address(),
-         acl = none          :: atom()}).
+-record(state, {myhost = <<"">> :: binary()}).
 
 %%%------------------------
 %%% gen_server callbacks
@@ -62,34 +55,32 @@ start_link(Host, Opts) ->
                          [Host, Opts], []).
 
 init([Host, Opts]) ->
-    State = parse_options(Host, Opts),
-    ejabberd_router:register_route(State#state.myhost, Host),
-    {ok, State}.
+    IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1,
+                             one_queue),
+    MyHost = gen_mod:get_opt_host(Host, Opts, <<"proxy.@HOST@">>),
+    gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
+                                 ?MODULE, process_disco_info, IQDisc),
+    gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS,
+                                 ?MODULE, process_disco_items, IQDisc),
+    gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_VCARD,
+                                 ?MODULE, process_vcard, IQDisc),
+    gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_BYTESTREAMS,
+                                 ?MODULE, process_bytestreams, IQDisc),
+    ejabberd_router:register_route(MyHost, Host),
+    {ok, #state{myhost = MyHost}}.
 
 terminate(_Reason, #state{myhost = MyHost}) ->
-    ejabberd_router:unregister_route(MyHost), ok.
-
-handle_info({route, From, To,
-            #xmlel{name = <<"iq">>} = Packet},
-           State) ->
-    IQ = jlib:iq_query_info(Packet),
-    case catch process_iq(From, IQ, State) of
-      Result when is_record(Result, iq) ->
-         ejabberd_router:route(To, From, jlib:iq_to_xml(Result));
-      {'EXIT', Reason} ->
-         ?ERROR_MSG("Error when processing IQ stanza: ~p",
-                    [Reason]),
-         Err = jlib:make_error_reply(Packet,
-                                     ?ERR_INTERNAL_SERVER_ERROR),
-         ejabberd_router:route(To, From, Err);
-      _ -> ok
-    end,
+    ejabberd_router:unregister_route(MyHost),
+    gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO),
+    gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS),
+    gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_VCARD),
+    gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_BYTESTREAMS).
+
+handle_info({route, From, To, #iq{} = Packet}, State) ->
+    ejabberd_router:process_iq(From, To, Packet),
     {noreply, State};
 handle_info(_Info, State) -> {noreply, State}.
 
-handle_call(get_port_ip, _From, State) ->
-    {reply, {port_ip, State#state.port, State#state.ip},
-     State};
 handle_call(_Request, _From, State) ->
     {reply, ok, State}.
 
@@ -102,185 +93,122 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
 %%%------------------------
 
 add_listener(Host, Opts) ->
-    State = parse_options(Host, Opts),
     NewOpts = [Host | Opts],
-    ejabberd_listener:add_listener({State#state.port,
-                                   State#state.ip},
+    ejabberd_listener:add_listener(get_port_ip(Host),
                                   mod_proxy65_stream, NewOpts).
 
 delete_listener(Host) ->
-    Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
-    {port_ip, Port, IP} = gen_server:call(Proc,
-                                         get_port_ip),
-    catch ejabberd_listener:delete_listener({Port, IP},
+    catch ejabberd_listener:delete_listener(get_port_ip(Host),
                                            mod_proxy65_stream).
 
 %%%------------------------
 %%% IQ Processing
 %%%------------------------
-
-%% disco#info request
-process_iq(_,
-          #iq{type = get, xmlns = ?NS_DISCO_INFO, lang = Lang} =
-              IQ,
-          #state{name = Name, serverhost = ServerHost}) ->
-    Info = ejabberd_hooks:run_fold(disco_info, ServerHost,
-                                  [], [ServerHost, ?MODULE, <<"">>, <<"">>]),
-    IQ#iq{type = result,
-         sub_el =
-             [#xmlel{name = <<"query">>,
-                     attrs = [{<<"xmlns">>, ?NS_DISCO_INFO}],
-                     children = iq_disco_info(Lang, Name) ++ Info}]};
-%% disco#items request
-process_iq(_,
-          #iq{type = get, xmlns = ?NS_DISCO_ITEMS} = IQ, _) ->
-    IQ#iq{type = result,
-         sub_el =
-             [#xmlel{name = <<"query">>,
-                     attrs = [{<<"xmlns">>, ?NS_DISCO_ITEMS}],
-                     children = []}]};
-%% vCard request
-process_iq(_,
-          #iq{type = get, xmlns = ?NS_VCARD, lang = Lang} = IQ,
-          _) ->
-    IQ#iq{type = result,
-         sub_el =
-             [#xmlel{name = <<"vCard">>,
-                     attrs = [{<<"xmlns">>, ?NS_VCARD}],
-                     children = iq_vcard(Lang)}]};
-%% bytestreams info request
-process_iq(JID,
-          #iq{type = get, sub_el = SubEl, lang = Lang,
-              xmlns = ?NS_BYTESTREAMS} =
-              IQ,
-          #state{acl = ACL, stream_addr = StreamAddr,
-                 serverhost = ServerHost}) ->
+-spec process_disco_info(iq()) -> iq().
+process_disco_info(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_disco_info(#iq{type = get, to = To, lang = Lang} = IQ) ->
+    Host = ejabberd_router:host_of_route(To#jid.lserver),
+    Name = gen_mod:get_module_opt(Host, mod_proxy65, name,
+                                 fun iolist_to_binary/1,
+                                 <<"SOCKS5 Bytestreams">>),
+    Info = ejabberd_hooks:run_fold(disco_info, Host,
+                                  [], [Host, ?MODULE, <<"">>, <<"">>]),
+    xmpp:make_iq_result(
+      IQ, #disco_info{xdata = Info,
+                     identities = [#identity{category = <<"proxy">>,
+                                             type = <<"bytestreams">>,
+                                             name =  translate:translate(Lang, Name)}],
+                     features = [?NS_DISCO_INFO, ?NS_DISCO_ITEMS,
+                                 ?NS_VCARD, ?NS_BYTESTREAMS]}).
+
+-spec process_disco_items(iq()) -> iq().
+process_disco_items(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_disco_items(#iq{type = get} = IQ) ->
+    xmpp:make_iq_result(IQ, #disco_items{}).
+
+-spec process_vcard(iq()) -> iq().
+process_vcard(#iq{type = set, lang = Lang} = IQ) ->
+    Txt = <<"Value 'set' of 'type' attribute is not allowed">>,
+    xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
+process_vcard(#iq{type = get, lang = Lang} = IQ) ->
+    Desc = translate:translate(Lang, <<"ejabberd SOCKS5 Bytestreams module">>),
+    Copyright = <<"Copyright (c) 2003-2016 ProcessOne">>,
+    xmpp:make_iq_result(
+      IQ, #vcard_temp{fn = <<"ejabberd/mod_proxy65">>,
+                     url = ?EJABBERD_URI,
+                     desc = <<Desc/binary, $\n, Copyright/binary>>}).
+
+-spec process_bytestreams(iq()) -> iq().
+process_bytestreams(#iq{type = get, from = JID, to = To, lang = Lang} = IQ) ->
+    Host = To#jid.lserver,
+    ServerHost = ejabberd_router:host_of_route(Host),
+    ACL = gen_mod:get_module_opt(ServerHost, mod_proxy65, access,
+                                fun acl:access_rules_validator/1,
+                                all),
     case acl:match_rule(ServerHost, ACL, JID) of
-      allow ->
-         StreamHostEl = [#xmlel{name = <<"streamhost">>,
-                                attrs = StreamAddr, children = []}],
-         IQ#iq{type = result,
-               sub_el =
-                   [#xmlel{name = <<"query">>,
-                           attrs = [{<<"xmlns">>, ?NS_BYTESTREAMS}],
-                           children = StreamHostEl}]};
-      deny ->
-         Txt = <<"Denied by ACL">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]}
+       allow ->
+           StreamHost = get_streamhost(Host, ServerHost),
+           xmpp:make_iq_result(IQ, #bytestreams{hosts = [StreamHost]});
+       deny ->
+           xmpp:make_error(IQ, xmpp:err_forbidden(<<"Denied by ACL">>, Lang))
     end;
-%% bytestream activation request
-process_iq(InitiatorJID,
-          #iq{type = set, sub_el = SubEl, lang = Lang,
-              xmlns = ?NS_BYTESTREAMS} =
-              IQ,
-          #state{acl = ACL, serverhost = ServerHost}) ->
+process_bytestreams(#iq{type = set, lang = Lang,
+                       sub_els = [#bytestreams{sid = undefined}]} = IQ) ->
+    Why = {missing_attr, <<"sid">>, <<"query">>, ?NS_BYTESTREAMS},
+    Txt = xmpp:format_error(Why),
+    xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
+process_bytestreams(#iq{type = set, lang = Lang,
+                       sub_els = [#bytestreams{sid = SID}]} = IQ)
+  when SID == <<"">> orelse length(SID) > 128 ->
+    Why = {bad_attr_value, <<"sid">>, <<"query">>, ?NS_BYTESTREAMS},
+    Txt = xmpp:format_error(Why),
+    xmpp:make_error(IQ, xmpp:err_bad_request(Txt, Lang));
+process_bytestreams(#iq{type = set, lang = Lang, 
+                       sub_els = [#bytestreams{activate = undefined}]} = IQ) ->
+    Why = {missing_cdata, <<"">>, <<"activate">>, ?NS_BYTESTREAMS},
+    Txt = xmpp:format_error(Why),
+    xmpp:make_error(IQ, xmpp:err_jid_malformed(Txt, Lang));
+process_bytestreams(#iq{type = set, lang = Lang, from = InitiatorJID, to = To,
+                       sub_els = [#bytestreams{activate = TargetJID,
+                                               sid = SID}]} = IQ) ->
+    ServerHost = ejabberd_router:host_of_route(To#jid.lserver),
+    ACL = gen_mod:get_module_opt(ServerHost, mod_proxy65, access,
+                                fun acl:access_rules_validator/1,
+                                all),
     case acl:match_rule(ServerHost, ACL, InitiatorJID) of
-      allow ->
-         ActivateEl = fxml:get_path_s(SubEl,
-                                     [{elem, <<"activate">>}]),
-         SID = fxml:get_tag_attr_s(<<"sid">>, SubEl),
-         case catch
-                jid:from_string(fxml:get_tag_cdata(ActivateEl))
-             of
-           TargetJID
-               when is_record(TargetJID, jid), SID /= <<"">>,
-                    byte_size(SID) =< 128, TargetJID /= InitiatorJID ->
-               Target =
-                   jid:to_string(jid:tolower(TargetJID)),
-               Initiator =
-                   jid:to_string(jid:tolower(InitiatorJID)),
-               SHA1 = p1_sha:sha(<<SID/binary, Initiator/binary, Target/binary>>),
-               case mod_proxy65_sm:activate_stream(SHA1, InitiatorJID,
-                                                   TargetJID, ServerHost)
-                   of
-                 ok -> IQ#iq{type = result, sub_el = []};
-                 false ->
-                     Txt = <<"Failed to activate bytestream">>,
-                     IQ#iq{type = error,
-                           sub_el = [SubEl, ?ERRT_ITEM_NOT_FOUND(Lang, Txt)]};
-                 limit ->
-                     Txt = <<"Too many active bytestreams">>,
-                     IQ#iq{type = error,
-                           sub_el = [SubEl, ?ERRT_RESOURCE_CONSTRAINT(Lang, Txt)]};
-                 conflict ->
-                     Txt = <<"Bytestream already activated">>,
-                     IQ#iq{type = error, sub_el = [SubEl, ?ERRT_CONFLICT(Lang, Txt)]};
-                 _ ->
-                     IQ#iq{type = error,
-                           sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}
-               end;
-           _ ->
-               Txt = <<"Malformed JID">>,
-               IQ#iq{type = error, sub_el = [SubEl, ?ERRT_BAD_REQUEST(Lang, Txt)]}
-         end;
-      deny ->
-         Txt = <<"Denied by ACL">>,
-         IQ#iq{type = error, sub_el = [SubEl, ?ERRT_FORBIDDEN(Lang, Txt)]}
-    end;
-%% Unknown "set" or "get" request
-process_iq(_, #iq{type = Type, sub_el = SubEl} = IQ, _)
-    when Type == get; Type == set ->
-    IQ#iq{type = error,
-         sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
-%% IQ "result" or "error".
-process_iq(_, _, _) -> ok.
-
+       allow ->
+           Target = jid:to_string(jid:tolower(TargetJID)),
+           Initiator = jid:to_string(jid:tolower(InitiatorJID)),
+           SHA1 = p1_sha:sha(<<SID/binary, Initiator/binary, Target/binary>>),
+           case mod_proxy65_sm:activate_stream(SHA1, InitiatorJID,
+                                               TargetJID, ServerHost) of
+               ok ->
+                   xmpp:make_iq_result(IQ);
+               false ->
+                   Txt = <<"Failed to activate bytestream">>,
+                   xmpp:make_error(IQ, xmpp:err_item_not_found(Txt, Lang));
+               limit ->
+                   Txt = <<"Too many active bytestreams">>,
+                   xmpp:make_error(IQ, xmpp:err_resource_constraint(Txt, Lang));
+               conflict ->
+                   Txt = <<"Bytestream already activated">>,
+                   xmpp:make_error(IQ, xmpp:err_conflict(Txt, Lang));
+               Err ->
+                   ?ERROR_MSG("failed to activate bytestream from ~s to ~s: ~p",
+                              [Initiator, Target, Err]),
+                   xmpp:make_error(IQ, xmpp:err_internal_server_error())
+           end;
+       deny ->
+           Txt = <<"Denied by ACL">>,
+           xmpp:make_error(IQ, xmpp:err_forbidden(Txt, Lang))
+    end.
 %%%-------------------------
 %%% Auxiliary functions.
 %%%-------------------------
--define(FEATURE(Feat),
-       #xmlel{name = <<"feature">>,
-              attrs = [{<<"var">>, Feat}], children = []}).
-
-iq_disco_info(Lang, Name) ->
-    [#xmlel{name = <<"identity">>,
-           attrs =
-               [{<<"category">>, <<"proxy">>},
-                {<<"type">>, <<"bytestreams">>},
-                {<<"name">>, translate:translate(Lang, Name)}],
-           children = []},
-     ?FEATURE((?NS_DISCO_INFO)), ?FEATURE((?NS_VCARD)),
-     ?FEATURE((?NS_BYTESTREAMS))].
-
-iq_vcard(Lang) ->
-    [#xmlel{name = <<"FN">>, attrs = [],
-           children = [{xmlcdata, <<"ejabberd/mod_proxy65">>}]},
-     #xmlel{name = <<"URL">>, attrs = [],
-           children = [{xmlcdata, ?EJABBERD_URI}]},
-     #xmlel{name = <<"DESC">>, attrs = [],
-           children =
-               [{xmlcdata,
-                 <<(translate:translate(Lang,
-                                        <<"ejabberd SOCKS5 Bytestreams module">>))/binary,
-                   "\nCopyright (c) 2003-2016 ProcessOne">>}]}].
-
-parse_options(ServerHost, Opts) ->
-    MyHost = gen_mod:get_opt_host(ServerHost, Opts,
-                                 <<"proxy.@HOST@">>),
-    Port = gen_mod:get_opt(port, Opts,
-                           fun(P) when is_integer(P), P>0, P<65536 -> P end,
-                           7777),
-    ACL = gen_mod:get_opt(access, Opts, fun acl:access_rules_validator/1,
-                          all),
-    Name = gen_mod:get_opt(name, Opts, fun iolist_to_binary/1,
-                          <<"SOCKS5 Bytestreams">>),
-    IP = gen_mod:get_opt(ip, Opts,
-                         fun(S) ->
-                                 {ok, Addr} = inet_parse:address(
-                                                binary_to_list(
-                                                  iolist_to_binary(S))),
-                                 Addr
-                         end, get_my_ip()),
-    HostName = gen_mod:get_opt(hostname, Opts,
-                               fun iolist_to_binary/1,
-                               jlib:ip_to_list(IP)),
-    StreamAddr = [{<<"jid">>, MyHost},
-                 {<<"host">>, HostName},
-                 {<<"port">>, jlib:integer_to_binary(Port)}],
-    #state{myhost = MyHost, serverhost = ServerHost,
-          name = Name, port = Port, ip = IP,
-          stream_addr = StreamAddr, acl = ACL}.
-
 transform_module_options(Opts) ->
     lists:map(
       fun({ip, IP}) when is_tuple(IP) ->
@@ -291,6 +219,33 @@ transform_module_options(Opts) ->
               Opt
       end, Opts).
 
+-spec get_streamhost(binary(), binary()) -> streamhost().
+get_streamhost(Host, ServerHost) ->
+    {Port, IP} = get_port_ip(ServerHost),
+    HostName = gen_mod:get_module_opt(ServerHost, mod_proxy65, hostname,
+                                     fun iolist_to_binary/1,
+                                     jlib:ip_to_list(IP)),
+    #streamhost{jid = jid:make(Host),
+               host = HostName,
+               port = Port}.
+
+-spec get_port_ip(binary()) -> {pos_integer(), inet:ip_address()}.
+get_port_ip(Host) ->
+    Port = gen_mod:get_module_opt(Host, mod_proxy65, port,
+                                 fun(P) when is_integer(P), P>0, P<65536 ->
+                                         P
+                                 end,
+                                 7777),
+    IP = gen_mod:get_module_opt(Host, mod_proxy65, ip,
+                               fun(S) ->
+                                       {ok, Addr} = inet_parse:address(
+                                                      binary_to_list(
+                                                        iolist_to_binary(S))),
+                                       Addr
+                               end, get_my_ip()),
+    {Port, IP}.
+
+-spec get_my_ip() -> inet:ip_address().
 get_my_ip() ->
     {ok, MyHostName} = inet:gethostname(),
     case inet:getaddr(MyHostName, inet) of
index d86b06c4bb9462549ac0efdec4469be5d6b3bd53..7ef4d390ee8e0fb9565c8911a629125b02f64e89 100644 (file)
 
 -record(state, {max_connections = infinity :: non_neg_integer() | infinity}).
 
--include("jlib.hrl").
-
 -record(bytestream,
        {sha1 = <<"">> :: binary() | '$1',
          target :: pid() | '_',
          initiator :: pid() | '_',
          active = false :: boolean() | '_',
-         jid_i = {<<"">>, <<"">>, <<"">>} :: ljid() | '_'}).
+         jid_i = {<<"">>, <<"">>, <<"">>} :: jid:ljid() | '_'}).
 
 -define(PROCNAME, ejabberd_mod_proxy65_sm).
 
index ae264bbc99b894879712ab641989a1853fead5ca..8f11b0eadaae9b512ecde1f753e09ea67775d49d 100644 (file)
@@ -62,9 +62,7 @@ log_user_receive(Packet, _C2SState, _JID, From, To) ->
     log_packet(From, To, Packet, To#jid.lserver),
     Packet.
 
-log_packet(From, To,
-          #xmlel{name = Name, attrs = Attrs, children = Els},
-          Host) ->
+log_packet(From, To, Packet, Host) ->
     Loggers = gen_mod:get_module_opt(Host, ?MODULE, loggers,
                                      fun(L) ->
                                              lists:map(
@@ -76,22 +74,11 @@ log_packet(From, To,
                                                        end
                                                end, L)
                                      end, []),
-    ServerJID = #jid{user = <<"">>, server = Host,
-                    resource = <<"">>, luser = <<"">>, lserver = Host,
-                    lresource = <<"">>},
-    NewAttrs =
-       jlib:replace_from_to_attrs(jid:to_string(From),
-                                  jid:to_string(To), Attrs),
-    FixedPacket = #xmlel{name = Name, attrs = NewAttrs,
-                        children = Els},
+    ServerJID = jid:make(Host),
+    FixedPacket = xmpp:set_from_to(Packet, From, To),
     lists:foreach(fun (Logger) ->
                          ejabberd_router:route(ServerJID,
-                                               #jid{user = <<"">>,
-                                                    server = Logger,
-                                                    resource = <<"">>,
-                                                    luser = <<"">>,
-                                                    lserver = Logger,
-                                                    lresource = <<"">>},
+                                               jid:make(Logger),
                                                #xmlel{name = <<"route">>,
                                                       attrs = [],
                                                       children =
index f738648d61111653873ab482f372d6f6178cea64..b75b6575b57bd6d9107c362c0bd03c9783669f40 100644 (file)
@@ -35,7 +35,7 @@
 -export([start/2, init/3, stop/1, get_sm_features/5,
         process_local_iq/1, process_sm_iq/1, string2lower/1,
         remove_user/2, export/1, import/1, import/3, depends/2,
-        process_search/1, process_vcard/1,
+        process_search/1, process_vcard/1, get_vcard/2,
         disco_items/5, disco_features/5, disco_identity/5,
         mod_opt_type/1, set_vcard/3, make_vcard_search/4]).
 
@@ -336,7 +336,7 @@ make_vcard_search(User, LUser, LServer, VCARD) ->
                  orgunit = OrgUnit,
                  lorgunit = LOrgUnit}.
 
--spec set_vcard(binary(), binary(), xmlel()) -> any().
+-spec set_vcard(binary(), binary(), xmlel()) -> {error, badarg} | ok.
 set_vcard(User, LServer, VCARD) ->
     case jid:nodeprep(User) of
        error ->