diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index b5a32c977..f2b4de026 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -29,8 +29,9 @@ start_link() -> init() -> MyDomain = ?MYNAME, ejabberd_router:register_local_route(MyDomain), + catch ets:new(local_iqtable, [named_table, public]), loop(#state{mydomain = MyDomain, - iqtable = ets:new(local_iqtable, [named_table])}). + iqtable = local_iqtable}). loop(State) -> receive diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index aaa3356fd..d88967b0f 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -97,8 +97,10 @@ init([From, Server, Type]) -> %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- open_socket(init, StateData) -> - case gen_tcp:connect(StateData#state.server, - ejabberd_config:get_local_option(outgoing_s2s_port), + {Addr, Port} = get_addr_port(StateData#state.server), + ?DEBUG("s2s_out: connecting to ~s:~p~n", [Addr, Port]), + case gen_tcp:connect(Addr, + Port, [binary, {packet, 0}]) of {ok, Socket} -> XMLStreamPid = xml_stream:start(self()), @@ -438,3 +440,28 @@ is_verify_res({xmlelement, Name, Attrs, Els}) when Name == "db:verify" -> is_verify_res(_) -> false. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SRV support + +-include_lib("kernel/include/inet.hrl"). + +get_addr_port(Server) -> + case inet_res:getbyname("_jabber._tcp." ++ Server, srv) of + {error, Reason} -> + ?DEBUG("srv lookup of '~s' failed: ~p~n", [Server, Reason]), + {Server, ejabberd_config:get_local_option(outgoing_s2s_port)}; + {ok, HEnt} -> + ?DEBUG("srv lookup of '~s': ~p~n", + [Server, HEnt#hostent.h_addr_list]), + case HEnt#hostent.h_addr_list of + [] -> + {Server, + ejabberd_config:get_local_option(outgoing_s2s_port)}; + [{_, _, Port, Host} | _] -> + {Host, Port} + end + end. + + + diff --git a/src/jd2ejd.erl b/src/jd2ejd.erl index 16ce514aa..1ec7ce5a1 100644 --- a/src/jd2ejd.erl +++ b/src/jd2ejd.erl @@ -13,7 +13,10 @@ -behaviour(gen_fsm). %% External exports --export([start/1, start/2, receiver/2]). +-export([start/1, + start/2, + import_file/1, + import_dir/1]). %% gen_fsm callbacks -export([init/1, @@ -28,7 +31,7 @@ -include("ejabberd.hrl"). -include("namespaces.hrl"). --record(state, {socket, receiver, +-record(state, {socket, user = "", server = ?MYNAME, resource = "" }). @@ -63,7 +66,6 @@ start(File, User) -> %% {stop, StopReason} %%---------------------------------------------------------------------- init([File, User]) -> - %ReceiverPid = spawn(?MODULE, receiver, [Socket, self()]), XMLStreamPid = xml_stream:start(self()), {ok, Text} = file:read_file(File), xml_stream:send_text(XMLStreamPid, Text), @@ -106,6 +108,14 @@ xdb_data({xmlstreamelement, El}, StateData) -> % {iq, "", set, ?NS_ROSTER, El}), mod_roster:set_items(StateData#state.user, El), StateData; + ?NS_VCARD -> + Res = mod_vcard:process_local_iq(From, + {"", ?MYNAME, ""}, + {iq, "", set, ?NS_VCARD, El}), + StateData; + "jabber:x:offline" -> + process_offline(From, El), + StateData; %?NS_REGISTER -> % mod_register:process_iq( % {"", "", ""}, {"", ?MYNAME, ""}, @@ -114,7 +124,7 @@ xdb_data({xmlstreamelement, El}, StateData) -> % io:format("user ~s~n", [User]), % StateData; XMLNS -> - io:format("Unknown namespace \"~s\"~n", [XMLNS]), + io:format("jd2ejd: Unknown namespace \"~s\"~n", [XMLNS]), StateData end, {next_state, xdb_data, NewState}; @@ -187,18 +197,44 @@ terminate(Reason, StateName, StateData) -> %%% Internal functions %%%---------------------------------------------------------------------- -receiver(Socket, C2SPid) -> - XMLStreamPid = xml_stream:start(C2SPid), - receiver(Socket, C2SPid, XMLStreamPid). +process_offline(To, {xmlelement, _, _, Els}) -> + lists:foreach(fun({xmlelement, _, Attrs, _} = El) -> + FromS = xml:get_attr_s("from", Attrs), + From = case FromS of + "" -> + {"", ?MYNAME, ""}; + _ -> + jlib:string_to_jid(FromS) + end, + case From of + error -> + ok; + _ -> + mod_offline:store_packet(From, To, El) + end + end, Els). + + +import_file(File) -> + start(File). + +import_dir(Dir) -> + {ok, Files} = file:list_dir(Dir), + MsgFiles = lists:filter( + fun(FN) -> + case string:len(FN) > 4 of + true -> + string:substr(FN, + string:len(FN) - 3) == ".xml"; + _ -> + false + end + end, Files), + lists:foreach( + fun(FN) -> + import_file(filename:join([Dir, FN])) + end, MsgFiles), + ok. + -receiver(Socket, C2SPid, XMLStreamPid) -> - case gen_tcp:recv(Socket, 0) of - {ok, Text} -> - xml_stream:send_text(XMLStreamPid, Text), - receiver(Socket, C2SPid, XMLStreamPid); - {error, Reason} -> - exit(XMLStreamPid, closed), - gen_fsm:send_event(C2SPid, closed), - ok - end. diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 6d0f1f2fc..7e62bff99 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -211,6 +211,42 @@ get_form(["running nodes", ENode, "modules", "start"], Lang) -> } ]}; +get_form(["running nodes", ENode, "import", "file"], Lang) -> + {result, [{xmlelement, "title", [], + [{xmlcdata, + translate:translate( + Lang, "Import User from File")}]}, + {xmlelement, "instructions", [], + [{xmlcdata, + translate:translate( + Lang, "Enter path to jabberd1.4 spool file")}]}, + {xmlelement, "field", [{"type", "text-single"}, + {"label", + translate:translate( + Lang, "Path to File")}, + {"var", "path"}], + [{xmlelement, "value", [], [{xmlcdata, ""}]}] + } + ]}; + +get_form(["running nodes", ENode, "import", "dir"], Lang) -> + {result, [{xmlelement, "title", [], + [{xmlcdata, + translate:translate( + Lang, "Import User from Dir")}]}, + {xmlelement, "instructions", [], + [{xmlcdata, + translate:translate( + Lang, "Enter path to jabberd1.4 spool dir")}]}, + {xmlelement, "field", [{"type", "text-single"}, + {"label", + translate:translate( + Lang, "Path to Dir")}, + {"var", "path"}], + [{xmlelement, "value", [], [{xmlcdata, ""}]}] + } + ]}; + get_form(["config", "hostname"], Lang) -> {result, [{xmlelement, "title", [], [{xmlcdata, @@ -363,6 +399,38 @@ set_form(["running nodes", ENode, "modules", "start"], Lang, XData) -> end; +set_form(["running nodes", ENode, "import", "file"], Lang, XData) -> + case search_running_node(ENode) of + false -> + {error, "404", "Not Found"}; + Node -> + case lists:keysearch("path", 1, XData) of + false -> + {error, "406", "Not Acceptable"}; + {value, {_, [String]}} -> + rpc:call(Node, jd2ejd, import_file, [String]); + _ -> + {error, "406", "Not Acceptable"} + end + end; + + +set_form(["running nodes", ENode, "import", "dir"], Lang, XData) -> + case search_running_node(ENode) of + false -> + {error, "404", "Not Found"}; + Node -> + case lists:keysearch("path", 1, XData) of + false -> + {error, "406", "Not Acceptable"}; + {value, {_, [String]}} -> + rpc:call(Node, jd2ejd, import_dir, [String]); + _ -> + {error, "406", "Not Acceptable"} + end + end; + + set_form(["config", "hostname"], Lang, XData) -> case lists:keysearch("hostname", 1, XData) of false -> diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 474eb2ac8..21a984f3d 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -132,6 +132,11 @@ process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) -> {iq, ID, result, XMLNS, [{xmlelement, "query", [{"xmlns", XMLNS}], [feature_to_xml({?NS_XDATA})]}]}; + ["running nodes", ENode, "import"] -> ?EMPTY_INFO_RESULT; + ["running nodes", ENode, "import", _] -> + {iq, ID, result, XMLNS, + [{xmlelement, "query", [{"xmlns", XMLNS}], + [feature_to_xml({?NS_XDATA})]}]}; ["config", _] -> {iq, ID, result, XMLNS, [{xmlelement, "query", [{"xmlns", XMLNS}], @@ -205,7 +210,9 @@ get_local_items(["stopped nodes"], Server, Lang) -> get_local_items(["running nodes", ENode], Server, Lang) -> {result, [?NODE("DB", "running nodes/" ++ ENode ++ "/DB"), - ?NODE("Modules", "running nodes/" ++ ENode ++ "/modules") + ?NODE("Modules", "running nodes/" ++ ENode ++ "/modules"), + ?NODE("Import users from jabberd1.4 spool files", + "running nodes/" ++ ENode ++ "/import") ]}; get_local_items(["running nodes", ENode, "DB"], Server, Lang) -> @@ -220,6 +227,15 @@ get_local_items(["running nodes", ENode, "modules"], Server, Lang) -> get_local_items(["running nodes", ENode, "modules", _], Server, Lang) -> {result, []}; +get_local_items(["running nodes", ENode, "import"], Server, Lang) -> + {result, + [?NODE("Import File", "running nodes/" ++ ENode ++ "/import/file"), + ?NODE("Import Directory", "running nodes/" ++ ENode ++ "/import/dir") + ]}; + +get_local_items(["running nodes", ENode, "import", _], Server, Lang) -> + {result, []}; + get_local_items(_, _, _) -> {error, "501", "Not Implemented"}.