From 88c9991f908314ecd9fbbacea42f994dfc0bf5b8 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 21 Dec 2015 16:19:24 +0100 Subject: [PATCH] Adding WEBIRC, custom realname & ident, ISO-8859-15 (thanks to iwalkalone69)(#877) --- src/mod_irc.erl | 46 +++++++++++++++++++++++++++++++++++--- src/mod_irc_connection.erl | 30 +++++++++++++++++-------- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/mod_irc.erl b/src/mod_irc.erl index c3664af0f..c6162d949 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -46,12 +46,16 @@ -include("adhoc.hrl"). --define(DEFAULT_IRC_ENCODING, <<"iso8859-1">>). +-define(DEFAULT_IRC_ENCODING, <<"iso8859-15">>). -define(DEFAULT_IRC_PORT, 6667). +-define(DEFAULT_REALNAME, <<"WebIRC-User">>). + +-define(DEFAULT_WEBIRC_PASSWORD, <<"">>). + -define(POSSIBLE_ENCODINGS, - [<<"koi8-r">>, <<"iso8859-1">>, <<"iso8859-2">>, + [<<"koi8-r">>, <<"iso8859-15">>, <<"iso8859-1">>, <<"iso8859-2">>, <<"utf-8">>, <<"utf-8+latin-1">>]). -type conn_param() :: {binary(), binary(), inet:port_number(), binary()} | @@ -379,11 +383,15 @@ do_route1(Host, ServerHost, From, To, Packet) -> %% username part of the JID). _ -> Username end, + Ident = extract_ident(Packet), + RemoteAddr = extract_ip_address(Packet), + RealName = get_realname(ServerHost), + WebircPassword = get_webirc_password(ServerHost), {ok, Pid} = mod_irc_connection:start(From, Host, ServerHost, Server, ConnectionUsername, Encoding, Port, - Password, ?MODULE), + Password, Ident, RemoteAddr, RealName, WebircPassword, ?MODULE), ets:insert(irc_connection, #irc_connection{jid_server_host = {From, Server, Host}, @@ -799,6 +807,12 @@ get_default_encoding(ServerHost) -> [ServerHost, Result]), Result. +get_realname(ServerHost) -> + gen_mod:get_module_opt(ServerHost, ?MODULE, realname, fun iolist_to_binary/1, ?DEFAULT_REALNAME). + +get_webirc_password(ServerHost) -> + gen_mod:get_module_opt(ServerHost, ?MODULE, webirc_password, fun iolist_to_binary/1, ?DEFAULT_WEBIRC_PASSWORD). + get_connection_params(Host, ServerHost, From, IRCServer) -> #jid{user = User, server = _Server} = From, @@ -1352,3 +1366,29 @@ mod_opt_type(default_encoding) -> mod_opt_type(host) -> fun iolist_to_binary/1; mod_opt_type(_) -> [access, db_type, default_encoding, host]. + +extract_ident(Packet) -> + case xml:get_subtag(Packet, <<"headers">>) of + {xmlel, _Name, _Attrs, Headers} -> + extract_header(<<"X-Irc-Ident">>, Headers); + _ -> + "chatmovil" + end. + +extract_ip_address(Packet) -> + case xml:get_subtag(Packet, <<"headers">>) of + {xmlel, _Name, _Attrs, Headers} -> + extract_header(<<"X-Forwarded-For">>, Headers); + _ -> + "127.0.0.1" + end. + +extract_header(HeaderName, [{xmlel, _Name, _Attrs, [{xmlcdata, Value}]} | Tail]) -> + case xml:get_attr(<<"name">>, _Attrs) of + {value, HeaderName} -> + binary_to_list(Value); + _ -> + extract_header(HeaderName, Tail) + end; +extract_header(_HeaderName, _Headers) -> + false. diff --git a/src/mod_irc_connection.erl b/src/mod_irc_connection.erl index 5c8597f2e..eed7006c9 100644 --- a/src/mod_irc_connection.erl +++ b/src/mod_irc_connection.erl @@ -30,7 +30,7 @@ -behaviour(gen_fsm). %% External exports --export([start_link/8, start/9, route_chan/4, +-export([start_link/12, start/13, route_chan/4, route_nick/3]). %% gen_fsm callbacks @@ -55,9 +55,13 @@ user = #jid{} :: jid(), host = <<"">> :: binary(), server = <<"">> :: binary(), + remoteAddr = <<"">> :: binary(), + ident = <<"">> :: binary(), + realname = <<"">> :: binary(), nick = <<"">> :: binary(), channels = dict:new() :: ?TDICT, nickchannel :: binary(), + webirc_password :: binary(), mod = mod_irc :: atom(), inbuf = <<"">> :: binary(), outbuf = <<"">> :: binary()}). @@ -78,18 +82,18 @@ -endif. start(From, Host, ServerHost, Server, Username, - Encoding, Port, Password, Mod) -> + Encoding, Port, Password, Ident, RemoteAddr, RealName, WebircPassword, Mod) -> Supervisor = gen_mod:get_module_proc(ServerHost, ejabberd_mod_irc_sup), supervisor:start_child(Supervisor, [From, Host, Server, Username, Encoding, Port, - Password, Mod]). + Password, Ident, RemoteAddr, RealName, WebircPassword, Mod]). start_link(From, Host, Server, Username, Encoding, Port, - Password, Mod) -> + Password, Ident, RemoteAddr, RealName, WebircPassword, Mod) -> gen_fsm:start_link(?MODULE, [From, Host, Server, Username, Encoding, Port, Password, - Mod], + Ident, RemoteAddr, RealName, WebircPassword, Mod], ?FSMOPTS). %%%---------------------------------------------------------------------- @@ -104,13 +108,14 @@ start_link(From, Host, Server, Username, Encoding, Port, %% {stop, StopReason} %%---------------------------------------------------------------------- init([From, Host, Server, Username, Encoding, Port, - Password, Mod]) -> + Password, Ident, RemoteAddr, RealName, WebircPassword, Mod]) -> gen_fsm:send_event(self(), init), {ok, open_socket, #state{queue = queue:new(), mod = Mod, encoding = Encoding, port = Port, password = Password, user = From, nick = Username, host = Host, - server = Server}}. + server = Server, ident = Ident, realname = RealName, + remoteAddr = RemoteAddr, webirc_password = WebircPassword }}. %%---------------------------------------------------------------------- %% Func: StateName/2 @@ -122,6 +127,10 @@ open_socket(init, StateData) -> Addr = StateData#state.server, Port = StateData#state.port, ?DEBUG("Connecting with IPv6 to ~s:~p", [Addr, Port]), + From = StateData#state.user, + #jid{user = JidUser, server = JidServer, resource = JidResource} = From, + UserIP = ejabberd_sm:get_user_ip(JidUser, JidServer, JidResource), + UserIPStr = inet_parse:ntoa(element(1, UserIP)), Connect6 = gen_tcp:connect(binary_to_list(Addr), Port, [inet6, binary, {packet, 0}]), Connect = case Connect6 of @@ -136,6 +145,8 @@ open_socket(init, StateData) -> case Connect of {ok, Socket} -> NewStateData = StateData#state{socket = Socket}, + send_text(NewStateData, + io_lib:format("WEBIRC ~s ~s ~s ~s\r\n", [StateData#state.webirc_password, JidResource, UserIPStr, UserIPStr])), if StateData#state.password /= <<"">> -> send_text(NewStateData, io_lib:format("PASS ~s\r\n", @@ -146,9 +157,10 @@ open_socket(init, StateData) -> io_lib:format("NICK ~s\r\n", [StateData#state.nick])), send_text(NewStateData, io_lib:format("USER ~s ~s ~s :~s\r\n", - [StateData#state.nick, StateData#state.nick, + [StateData#state.ident, + StateData#state.nick, StateData#state.host, - StateData#state.nick])), + StateData#state.realname])), {next_state, wait_for_registration, NewStateData}; {error, Reason} -> ?DEBUG("connect return ~p~n", [Reason]),